Dart 基礎 - 4
同步發(fā)表於筆者部落格
目的:
- 為公司內(nèi)部分享的筆記。
- 寫給想由淺入深地了解 Dart 這個(gè)程式語言的人。
類別(Class) - 中篇
延續(xù)上一節(jié)的 類別(Class) - 上篇
方法(Methods)
Dart 中有幾種類別中的方法:
- 實(shí)例方法(Instance methods) - 就是一般類別中標(biāo)準(zhǔn)的函數(shù),使用的時(shí)候要先以類別實(shí)例化出物件,該物件才能使用此方法。
- 靜態(tài)方法(Static methods) - 跟一般類別中的函數(shù)很像,不過它不用實(shí)例化便可使用該方法,通常是與該類別相關(guān)所以會(huì)定義在類別裡。
- 抽象方法(Abstract methods) - 抽象類別中的函數(shù),用來定義樣板,繼承該抽象類別後所需實(shí)現(xiàn)(implement)的函數(shù)。
- Getters & Setters - 範(fàn)例中 Complex 的 real 和 imaginary
- 運(yùn)算子方法(Operator methods) - Dart 中可以 Override 幾個(gè)常用的運(yùn)算子的方法,如 + - * / > < ==... 等等。
!= 是不可複寫的,因?yàn)樗喈?dāng)於 !(a == b)
我們?cè)?Complex 中再加入些方法吧
class Complex {// Private property(member)num _real;num _imaginary;// Getters & Settersget real => _real;set real(num newReal) => _real = newReal;get imaginary => _imaginary;set imaginary(num newImaginary) => _imaginary = newImaginary;// ConstructorsComplex(this._real, this._imaginary);Complex.real(num real) : this(real, 0);Complex.imaginary(num imaginary) : this(0, imaginary);Complex multiply(Complex c) {return Complex((this.real * c.real) - (this.imaginary * c.imaginary),(this.real * c.imaginary) + (this.imaginary * c.real),);}static Complex substract(Complex c1, Complex c2) {return Complex(c1.real - c2.real,c1.imaginary - c2.imaginary,);}Complex operator +(Complex c) {return Complex(this.real + c.real, this.imaginary + c.imaginary);}bool operator ==(dynamic other) {if (other is! Complex) {return false;} else {return real == other.real && imaginary == other.imaginary;}}String toString() {if (imaginary >= 0) {return "$real + ${imaginary}i";} else {return "$real - ${imaginary.abs()}i";}} } 復(fù)制代碼- 實(shí)例方法(Instance methods) - Complex.multiply
- 靜態(tài)方法(Static methods) - Complex.substract
- 運(yùn)算子方法(Operator methods) - Complex.+
按照邏輯,數(shù)學(xué)上的運(yùn)算覆寫 運(yùn)算子方法(Operator methods) 會(huì)比較合理。
這邊展示用所以才拆開;而 抽象方法(Abstract methods) 使用情況較特別,後面會(huì)在講述。
使用看看這些方法吧
var n1 = Complex(3, -4); var n2 = Complex(5, 2);print(n1 + n2); print(n1.multiply(n2)); print(Complex.substract(n1, n2)); 復(fù)制代碼8 - 2i 23 - 14i -2 - 6i 復(fù)制代碼final & const
final 與 const 變數(shù)在 Dart 中是常見的,在大部份的情況下他們的結(jié)果是相同的,就是不能任意更改賦予此變數(shù)的值。
但實(shí)際意義上是有些不同的,final 是指第一次賦予此變數(shù)值之後就不能作改變了,也就是 final 的作用是發(fā)生於 Run-time 的,是程式執(zhí)行當(dāng)下決定; 而 const 是在 Compile-time 就決定,所以在程式編譯後就已經(jīng)決定好了,程式執(zhí)行當(dāng)下也不能作改變。
在物件導(dǎo)向(OO)的類別中,常用 final 在類別的屬性,目的在於創(chuàng)建物件(實(shí)例)後希望該屬性不再改變,比如在 Complex 得屬性中加上 final。
但後續(xù) real 和 imaginary Setter 方法就都不能使用,會(huì)出現(xiàn) '_real' can't be used as a setter because it is final. 的錯(cuò)誤。
class Complex {// Private property(member)final num _real;final num _imaginary;get real => _real;set real(num newReal) => _real = newReal; // 會(huì)出現(xiàn) Error. get imaginary => _imaginary;set imaginary(num newImaginary) => _imaginary = newImaginary; // 會(huì)出現(xiàn) Error.... } 復(fù)制代碼而 const 在物件中,需寫成 static const 通常都是常用且不變的類別屬性,比如 dart:math 中的數(shù)學(xué)常數(shù)、package:http/http.dart 中的 HttpHeaders。
// dart:math/*** Base of the natural logarithms.** Typically written as "e".*/ const double e = 2.718281828459045;.../*** The PI constant.*/ const double pi = 3.1415926535897932;... 復(fù)制代碼// package:http/http.dartabstract class HttpHeaders {static const acceptHeader = "accept";static const acceptCharsetHeader = "accept-charset";static const acceptEncodingHeader = "accept-encoding";static const acceptLanguageHeader = "accept-language";static const acceptRangesHeader = "accept-ranges";static const ageHeader = "age";static const allowHeader = "allow";static const authorizationHeader = "authorization";... } 復(fù)制代碼繼承(Inheritance) - 擴(kuò)展(extends)
物件導(dǎo)向(Object-Oriented)中的繼承,是一個(gè)非常核心的概念,可細(xì)分非常多種。
要理解很多種概念(或是設(shè)計(jì)模式),才有辦法做出更好程式設(shè)計(jì)。
這邊主要講的是 extends (擴(kuò)展、延伸)。
標(biāo)準(zhǔn)的寫法 class 子類 extends 父類(基類)。
這樣的用法主要是子類必須包含父類的所有特性,並且有自己的額外特性。此用法可以達(dá)成程式碼重用(reuse)效果。
注意: Dart 中的 extends 只支援單一繼承。
Dart 簡(jiǎn)單一點(diǎn)的繼承應(yīng)用,可以看到 num、int 和 double 的繼承關(guān)係。
abstract class double extends num {static const double nan = 0.0 / 0.0;static const double infinity = 1.0 / 0.0;static const double negativeInfinity = -infinity;static const double minPositive = 5e-324;static const double maxFinite = 1.7976931348623157e+308; double remainder(num other);... } 復(fù)制代碼abstract class int extends num { ...int gcd(int other);/** Returns true if and only if this integer is even. */bool get isEven;/** Returns true if and only if this integer is odd. */bool get isOdd;... } 復(fù)制代碼- 除了 num 的基本特性,int 和 double 多了自己的特性。
複雜一點(diǎn),可以看 Flutter 中的 ListView 和 BoxScrollView 的繼承關(guān)係。
class ListView extends BoxScrollView {ListView({Key key,Axis scrollDirection = Axis.vertical,bool reverse = false,ScrollController controller,bool primary,ScrollPhysics physics,bool shrinkWrap = false,EdgeInsetsGeometry padding,this.itemExtent,bool addAutomaticKeepAlives = true,bool addRepaintBoundaries = true,bool addSemanticIndexes = true,double cacheExtent,List<Widget> children = const <Widget>[],int semanticChildCount,}) : childrenDelegate = SliverChildListDelegate(children,addAutomaticKeepAlives: addAutomaticKeepAlives,addRepaintBoundaries: addRepaintBoundaries,addSemanticIndexes: addSemanticIndexes,), super(key: key,scrollDirection: scrollDirection,reverse: reverse,controller: controller,primary: primary,physics: physics,shrinkWrap: shrinkWrap,padding: padding,cacheExtent: cacheExtent,semanticChildCount: semanticChildCount ?? children.length,);...final double itemExtent;final SliverChildDelegate childrenDelegate;Widget buildChildLayout(BuildContext context) {if (itemExtent != null) {return SliverFixedExtentList(delegate: childrenDelegate,itemExtent: itemExtent,);}return SliverList(delegate: childrenDelegate);}void debugFillProperties(DiagnosticPropertiesBuilder properties) {super.debugFillProperties(properties);properties.add(DoubleProperty('itemExtent', itemExtent, defaultValue: null));}// Helper method to compute the semantic child count for the separated constructor.static int _computeSemanticChildCount(int itemCount) {return math.max(0, itemCount * 2 - 1);} } 復(fù)制代碼- ListView 的建構(gòu)子中的初始列表,把相當(dāng)多的特性都用 super 傳給了父類 BoxScrollView。
- ListView 擁有自己的特性,如屬性 itemExtent 、 childrenDelegate;方法 _computeSemanticChildCount。
- ListView 也覆寫了父類的特性,如 buildChildLayout 和 debugFillProperties。
物件導(dǎo)向中的繼承是個(gè)概念簡(jiǎn)單,但實(shí)際上使用可以相當(dāng)複雜。
需要多看多寫程式碼才能更加深入了解這概念的博大精深。
重構(gòu)也是程序員常做事情,畢竟人也是會(huì)慢慢進(jìn)步,會(huì)發(fā)現(xiàn)以前寫的程式碼的一些缺陷,進(jìn)而改進(jìn)。
你也可以瞧瞧...
參考
- Dart 官方文檔 - Final and const
- Dart 官方文檔 - Classes
- Introduction to Dart for Beginners - Methods, Final, Static and Basic Class Inheritance - Part Four
系列文
- Dart 基礎(chǔ) - 5
總結(jié)
以上是生活随笔為你收集整理的Dart 基礎 - 4的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: prometheus + influxd
- 下一篇: FastAdmin 极速后台管理框架(三