2020-04-11 Flutter學(xué)習(xí)筆記——Dart構(gòu)造函數(shù)介紹

Dart構(gòu)造函數(shù)有4種格式:

ClassName(...) ? //類名構(gòu)造函數(shù)

Classname.identifier(...) ? //命名構(gòu)造函數(shù)

const ClassName(...)?? //常量構(gòu)造函數(shù)

factroy ClassName(...)?? //工廠構(gòu)造函數(shù)


1. 默認(rèn)構(gòu)造函數(shù)

如果你定義了一個(gè)類,而沒(méi)有定義構(gòu)造函數(shù),那么它將有一個(gè)默認(rèn)的構(gòu)造函數(shù),這個(gè)構(gòu)造函數(shù)沒(méi)有參數(shù)

如果這個(gè)類有父類,那么默認(rèn)構(gòu)造函數(shù),還會(huì)調(diào)用父類的無(wú)參數(shù)構(gòu)造函數(shù)。

2. 類名構(gòu)造函數(shù)

構(gòu)造函數(shù)就是一個(gè)與類同名的函數(shù),構(gòu)造函數(shù)是一個(gè)函數(shù),因此可以參數(shù)化。但是與函數(shù)不同,構(gòu)造函數(shù)不能具有返回類型。

class Point {

? num x, y;

? // 類名構(gòu)造函數(shù)

Point(num x, num y) {

??? // There's abetter way to do this, stay tuned.

??? this.x = x;

??? this.y = y;

? }

}

上例中只有兩個(gè)成員變量,如果有10個(gè),豈不是麻煩死?所以Dart有語(yǔ)法糖如下:

class Point {

? num x, y;

? // Syntacticsugar for setting x and y

? // before theconstructor body runs.

? Point(this.x,this.y);

}

它可以將x,y的賦值變得簡(jiǎn)單一些,就不用寫構(gòu)造函數(shù)的方法體了,記得括號(hào)后用分號(hào)哦。

3. 命名構(gòu)造函數(shù)

在Dart中構(gòu)造函數(shù)的名稱可以是類名 ClassName 或者類名和標(biāo)識(shí)符 ClassName.identifier 。 其中構(gòu)造函數(shù)名稱是“ClassName”的函數(shù)叫“類名構(gòu)造函數(shù)”;構(gòu)造函數(shù)名稱是“ClassName.identifier”的函數(shù)叫“命名構(gòu)造函數(shù)”。

class Point {

? num x, y;

? // 類名構(gòu)造函數(shù)

Point(this.x, this.y);

? // 命名構(gòu)造函數(shù)

? Point.origin() {

??? x= 0;

??? y= 0;

? }

// 命名構(gòu)造函數(shù)

? Point.now(num x, num y)

? {

????? print("這是命名構(gòu)造函數(shù)");

????? this.x = x;

????? this.y = y;

?? }

}

使用命名構(gòu)造函數(shù)可以為類提供多個(gè)構(gòu)造函數(shù),以使類定義多個(gè)構(gòu)造函數(shù)。

請(qǐng)記住,命名構(gòu)造函數(shù)不可繼承,如果子類想要有 和父類一樣的命名構(gòu)造函數(shù),那就寫個(gè)同名的(通常也會(huì)在子類的命名構(gòu)造函數(shù)里,調(diào)用父類的同名命名構(gòu)造函數(shù))



再看一個(gè)實(shí)際例子,加深一下用命名構(gòu)造函數(shù)的好處:橫向擴(kuò)展

RaisedButton 即"漂浮"按鈕,它默認(rèn)帶有陰影和灰色背景。按下后,陰影會(huì)變大,如圖3-10所示:


使用RaisedButton非常簡(jiǎn)單,如:

RaisedButton(?//類名構(gòu)造函數(shù)

? child: Text("normal"),

? onPressed: () {},

);

RaisedButton、FlatButton、OutlineButton都有一個(gè)icon 構(gòu)造函數(shù),通過(guò)它可以輕松創(chuàng)建帶圖標(biāo)的按鈕,如圖3-14所示:


代碼如下:

RaisedButton.icon(?//命名構(gòu)造函數(shù)

? icon:Icon(Icons.send),

? label:Text("發(fā)送"),

? onPressed: _onPressed,

),

OutlineButton.icon(

? icon:Icon(Icons.add),

? label:Text("添加"),

? onPressed:_onPressed,

),

FlatButton.icon(

? icon:Icon(Icons.info),

? label:Text("詳情"),

? onPressed:_onPressed,

),

3.2重定向構(gòu)造函數(shù)(構(gòu)造函數(shù)傳遞)

有時(shí)構(gòu)造函數(shù)的唯一目的是重定向到同一類中的另一個(gè)構(gòu)造函數(shù)。定義構(gòu)造函數(shù)的時(shí)候,除了一個(gè)普通構(gòu)造函數(shù),還可以有若干命名構(gòu)造函數(shù),這些構(gòu)造函數(shù)之間,有時(shí)候會(huì)有一些相同的邏輯,如果分別書寫在各個(gè)構(gòu)造函數(shù)中,會(huì)有些多余,所以構(gòu)造函數(shù)可以傳遞。重定向構(gòu)造函數(shù)沒(méi)有方法體,會(huì)在初始化列表中,構(gòu)造函數(shù)調(diào)用出現(xiàn)在冒號(hào)( :)之后 。 就是在創(chuàng)建類時(shí),定義一個(gè)命名構(gòu)造函數(shù),但是這個(gè)構(gòu)造函式的主體不實(shí)現(xiàn),直接通過(guò)另外一個(gè)構(gòu)造函數(shù)實(shí)現(xiàn)對(duì)外界傳入的參數(shù)接收并賦值給內(nèi)部的變量。

class Point {

? num x, y;

? // The main constructor for this class.

? Point(this.x, this.y);

? // Delegates to the main constructor.

? Point.alongXAxis(Map<String, num> json)

??? :x = json['x'],

????? y= json['y'] {

? print('In Point.fromJson(): ($x, $y)');

}? //初始化列表就是構(gòu)造函數(shù)名的冒號(hào)后面,打括號(hào)前面的部分。

}

初始化列表的執(zhí)行順序,在整個(gè)構(gòu)造函數(shù)的最前面,它除了可以調(diào)用父類的構(gòu)造函數(shù),還可以在構(gòu)造函數(shù)方法體之前,初始化一些成員變量。

import 'dart:math';

class Point {

? final num x;

? final num y;

? final num distanceFromOrigin;

? Point(x, y)

????? :x = x,

??????? y= y,

??????? distanceFromOrigin= sqrt(x * x + y * y);

}

main() {

? var p = new Point(2, 3);

? print(p.distanceFromOrigin);

}


再看計(jì)數(shù)器示例的代碼,是不是有感覺了:語(yǔ)法糖和初始化列表都出現(xiàn)了

class MyHomePage extends StatefulWidget {

? MyHomePage({Key key

, this.title}) : super(key: key);

// This widget is the home page of your application. It is stateful, meaning

? // that it has a State object (defined below) that contains fields that affect

? // how it looks.

? // This class is the configuration for the state. It holds the values (in this

? // case the title) provided by the parent (in this case the App widget) and

? // used by the build method of the State. Fields in a Widget subclass are

? // always marked "final".

final String title;


4. 常量構(gòu)造函數(shù)

class ImmutablePoint {

? static final ImmutablePoint origin =

????? const ImmutablePoint(0, 0);

? final num x, y;

? const ImmutablePoint(this.x, this.y);

}

如果你的類,創(chuàng)建的對(duì)象永遠(yuǎn)不會(huì)改變,你可以在編譯期就創(chuàng)建這個(gè)常量實(shí)例,并且定義一個(gè)常量構(gòu)造函數(shù),并且確保所有的成員變量都是final的。


5. 工廠構(gòu)造函數(shù)

有時(shí)候可能有一種需求,并不需要每次都創(chuàng)建新的類實(shí)例,而是每一種情況,只需要一個(gè)實(shí)例:

class Logger {

? final String name;

? bool mute= false;

? // _cache is library-private, thanks to the _ in front of its name.

? static final Map<String, Logger> _cache =

????? <String, Logger>{};

? factory Logger(String name) {

??? if (_cache.containsKey(name)) {

?????return _cache[name];

??? } else {

????? final logger = Logger._internal(name);

????? _cache[name] = logger;

????? return logger;

??? }

? }

? Logger._internal(this.name);

? void log(String msg) {

??? if (!mute) print(msg);

? }

}

main() {

??? var logger = Logger('UI');

??? logger.log('Button clicked');

}

工廠構(gòu)造函數(shù),沒(méi)有權(quán)利訪問(wèn)this

上例的意思是,類中又一個(gè)靜態(tài)緩存_cache保存著一些Logger類實(shí)例,創(chuàng)建實(shí)例時(shí),給工廠構(gòu)造函數(shù)傳遞的name,如果在緩存中已經(jīng)存在,就用緩存中現(xiàn)成的實(shí)例,如果沒(méi)有,就新建一個(gè)實(shí)例,并且也放到緩存中。

如此這般,我們可以創(chuàng)建名字為UI / SYS / API 等的實(shí)例,然后在debug的時(shí)候,如果設(shè)置名字為UI的Logger實(shí)例的mute為true,就不會(huì)打印UI相關(guān)的log,而不影響其它兩個(gè)名字的log。是不是很方便呢?

尾記:

學(xué)習(xí)Dart語(yǔ)法時(shí)建議結(jié)合實(shí)際例子中的用法去理解,語(yǔ)法特性也是為實(shí)際場(chǎng)景服務(wù)的,掌握背后的意義,才能真正掌握一門工具,用好一門語(yǔ)言。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容