Dart語法快速上手五 《Dart2之類與構(gòu)造方法》


使用構(gòu)造方法

var p1 = Point(2, 2);
var p2 = Point.fromJson({'x': 1, 'y': 2});

var p1 = new Point(2, 2);
var p2 = new Point.fromJson({'x': 1, 'y': 2});

上面這兩種寫法都是可以的慷嗜,Dart2中new關(guān)鍵字已經(jīng)成為一個(gè)可選項(xiàng)

常量構(gòu)造方法

有些類提供常量構(gòu)造函數(shù)卿捎。要使用常量構(gòu)造函數(shù)創(chuàng)建編譯時(shí)常量,請將const關(guān)鍵字放在構(gòu)造函數(shù)名稱之前

var p = const ImmutablePoint(2, 2);

構(gòu)造兩個(gè)相同的編譯時(shí)常量會產(chǎn)生一個(gè)規(guī)范的實(shí)例:

var a = const ImmutablePoint(1, 1);
var b = const ImmutablePoint(1, 1);

assert(identical(a, b)); // They are the same instance!

如果將const關(guān)鍵字前置的話,后面的const是可以省略的珍剑,比如

// Lots of const keywords here.
const pointAndLine = const {
  'point': const [const ImmutablePoint(0, 0)],
  'line': const [const ImmutablePoint(1, 10), const ImmutablePoint(-2, 11)],
};

上面的代碼可以寫成

// Only one const, which establishes the constant context.
const pointAndLine = {
  'point': [ImmutablePoint(0, 0)],
  'line': [ImmutablePoint(1, 10), ImmutablePoint(-2, 11)],
};

獲取運(yùn)行時(shí)類型

要在運(yùn)行時(shí)獲取對象的類型贫堰,可以使用Object的runtimeType屬性穆壕,該屬性返回Type對象。

print('The type of a is ${a.runtimeType}');

聲明構(gòu)造函數(shù)

class Point {
  num x, y;

  // Syntactic sugar for setting x and y
  // before the constructor body runs.
  Point(this.x, this.y);
}

上面是一種簡化版的構(gòu)造函數(shù)其屏,只是為了賦值喇勋,所以省略了方法體

如果您未聲明構(gòu)造函數(shù),則會為您提供默認(rèn)構(gòu)造函數(shù)偎行。
默認(rèn)構(gòu)造函數(shù)沒有參數(shù)川背,并在超類中調(diào)用無參數(shù)構(gòu)造函數(shù)。

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

使用命名構(gòu)造函數(shù)為類實(shí)現(xiàn)多個(gè)構(gòu)造函數(shù)或提供額外的清晰度:

class Point {
  num x, y;

  Point(this.x, this.y);

  // Named constructor
  Point.origin() {
    x = 0;
    y = 0;
  }
}

跟Java等語言不同蛤袒,Dart的多重構(gòu)造方法是一種類名.自定義方法名來實(shí)現(xiàn)的熄云,如果你按照傳統(tǒng)的方法來寫的話,例如這樣:

class Grammar2 {
  var x, y, z;

  Grammar2(this.x,this.y);  //錯(cuò)誤

  Grammar2(this.x); //不能同時(shí)擁有兩個(gè)這樣的構(gòu)造函數(shù)

}

正確的寫法

class Grammar2 {
  var x, y, z;

  Grammar2.translate(this.x, this.y); //TODO 構(gòu)造方法的重載

  Grammar2(this.x,this.y);
  

   printRealVar() {
    print('x=' + x.toString() + "y=" + y.toString());
    return 2;
  }

 @override
  String toString() {
    // TODO: implement toString
    return "this is Grammar2";
  }
}

調(diào)用非默認(rèn)的超類構(gòu)造函數(shù)

默認(rèn)情況下妙真,子類中的構(gòu)造函數(shù)調(diào)用超類的未命名的無參數(shù)構(gòu)造函數(shù)缴允。
超類的構(gòu)造函數(shù)在構(gòu)造函數(shù)體的開頭被調(diào)用。
如果還使用初始化列表珍德,則在調(diào)用超類之前執(zhí)行练般。
總之,執(zhí)行順序如下:

class Person {
  String firstName;

  Person.fromJson(Map data) {
    print('in Person');
  }
}

class Employee extends Person {
  // Person does not have a default constructor;
  // you must call super.fromJson(data).
  Employee.fromJson(Map data) : super.fromJson(data) {
    print('in Employee');
  }
}

main() {
  var emp = new Employee.fromJson({});

  // Prints:
  // in Person
  // in Employee
  if (emp is Person) {
    // Type check
    emp.firstName = 'Bob';
  }
  (emp as Person).firstName = 'Bob';
}

這段代碼的執(zhí)行結(jié)果就是:
in Person
in Employee

除了調(diào)用超類構(gòu)造函數(shù)之外锈候,還可以在構(gòu)造函數(shù)體運(yùn)行之前初始化實(shí)例變量薄料。
用冒號分隔初始化程序。

// Initializer list sets instance variables before
// the constructor body runs.
Point.fromJson(Map<String, num> json)
    : x = json['x'],
      y = json['y'] {
  print('In Point.fromJson(): ($x, $y)');
}

這個(gè)示例中泵琳,我們在調(diào)用fromjson這個(gè)構(gòu)造方法之前我們搶先初始化了x和y的值摄职,中間用冒號隔開

你也可以在調(diào)用初始化方法之前進(jìn)行一些參數(shù)的驗(yàn)證,比如:

Point.withAssert(this.x, this.y) : assert(x >= 0) {
  print('In Point.withAssert(): ($x, $y)');
}

這個(gè)示例中获列,構(gòu)造方法調(diào)用之前琳钉,我們驗(yàn)證了x必須為正數(shù)

構(gòu)造函數(shù)的重定向

我們在開發(fā)中經(jīng)常會有這樣的情景,我們構(gòu)造了好幾個(gè)構(gòu)造方法蛛倦,但是這些構(gòu)造方法本身并不執(zhí)行任何操作歌懒,只是為了調(diào)用其他構(gòu)造 方法,在Dart中溯壶,我們稱之為構(gòu)造方法的重定向(這個(gè)語法在前面示例中出現(xiàn)過)

class Point {
  num x, y;

  // The main constructor for this class.
  Point(this.x, this.y);

  // Delegates to the main constructor.
  Point.alongXAxis(num x) : this(x, 0);
}

常量構(gòu)造方法

假如你的示例在整個(gè)程序從始至終都不會變更實(shí)例及皂,這個(gè)時(shí)候你可以考慮一下使用常量構(gòu)造方法甫男,在構(gòu)造方法前面加上const關(guān)鍵字(是不是很像單例模式?)

class ImmutablePoint {
  static final ImmutablePoint origin =
      const ImmutablePoint(0, 0);

  final num x, y;

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

工廠構(gòu)造方法

跟工廠設(shè)計(jì)模式類似验烧,需要什么給你什么板驳,根據(jù)一個(gè)特定的標(biāo)識產(chǎn)生不同的實(shí)例,在Dart中碍拆,通過傳入一個(gè)特定的標(biāo)識符若治,來查看我的靜態(tài)緩存里面有沒有這個(gè)緩存,如果有感混,直接返回端幼,如果沒有,我便new 一個(gè)對象存入緩存再返回

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);
  }
}

工廠構(gòu)造函數(shù)無權(quán)訪問 this

對象之間的操作符運(yùn)算

您可以覆蓋下表中顯示的運(yùn)算符弧满。
例如婆跑,如果定義Vector類,則可以定義一個(gè)+方法來添加兩個(gè)向量庭呜。(翻譯自官網(wǎng))


image.png

來個(gè)示例滑进,自己體會

class Vector {
  final int x, y;

  Vector(this.x, this.y);

  Vector operator +(Vector v) => Vector(x + v.x, y + v.y);
  Vector operator -(Vector v) => Vector(x - v.x, y - v.y);

  // Operator == and hashCode not shown. For details, see note below.
  // ···
}

void main() {
  final v = Vector(2, 3);
  final w = Vector(2, 2);

  assert(v + w == Vector(4, 5));
  assert(v - w == Vector(0, 1));
}

要在代碼嘗試使用不存在的方法或?qū)嵗兞繒r(shí)檢測或做出反應(yīng),您可以覆蓋noSuchMethod():

class A {
  // Unless you override noSuchMethod, using a
  // non-existent member results in a NoSuchMethodError.
  @override
  void noSuchMethod(Invocation invocation) {
    print('You tried to use a non-existent member: ' +
        '${invocation.memberName}');
  }
}

枚舉類

enum Color { red, green, blue }

枚舉中的每個(gè)值都有一個(gè)索引getter募谎,它返回枚舉聲明中值的從零開始的位置扶关。
例如,第一個(gè)值具有索引0数冬,第二個(gè)值具有索引1节槐。

assert(Color.red.index == 0);
assert(Color.green.index == 1);
assert(Color.blue.index == 2);

要獲取枚舉中所有值的列表,請使用枚舉值常量吉执。

List<Color> colors = Color.values;
assert(colors[2] == Color.blue);

switch case中使用枚舉

var aColor = Color.blue;

switch (aColor) {
  case Color.red:
    print('Red as roses!');
    break;
  case Color.green:
    print('Green as grass!');
    break;
  default: // Without this, you see a WARNING.
    print(aColor); // 'Color.blue'
}

Mixin

Mixins是一種在多個(gè)類層次結(jié)構(gòu)中重用類代碼的方法,B繼承于A地来,但是B也要用到C的一些特性戳玫,多繼承在很多語言中是行不通的,Dart中的Mixin就是為了解決這種問題出現(xiàn)的

要使用mixin未斑,請使用with關(guān)鍵字咕宿,后跟一個(gè)或多個(gè)mixin名稱。
以下示例顯示了兩個(gè)使用mixins的類:

class Musician extends Performer with Musical {
  // ···
}

class Maestro extends Person
    with Musical, Aggressive, Demented {
  Maestro(String maestroName) {
    name = maestroName;
    canConduct = true;
  }
}

注意:要實(shí)現(xiàn)一個(gè)mixin蜡秽,創(chuàng)建一個(gè)擴(kuò)展Object的類府阀,聲明沒有構(gòu)造函數(shù),并且沒有調(diào)用super芽突。
例如:

abstract class Musical {
  bool canPlayPiano = false;
  bool canCompose = false;
  bool canConduct = false;

  void entertainMe() {
    if (canPlayPiano) {
      print('Playing piano');
    } else if (canConduct) {
      print('Waving hands');
    } else {
      print('Humming to self');
    }
  }
}

泛型方法(只看代碼不解釋试浙,跟java幾乎一樣)

T first<T>(List<T> ts) {
  // Do some initial work or error checking, then...
  T tmp = ts[0];
  // Do some additional checking or processing...
  return tmp;
}

導(dǎo)入

Dart目前都要手動(dòng)導(dǎo)入包,Dart內(nèi)置的library可以直接用import 'Interface.dart';方法導(dǎo)入寞蚌,自定義的包可以在前面加入一個(gè)package關(guān)鍵字導(dǎo)入

import 'package:flutter_app/Grammar2.dart';
import 'SuperGrammar.dart';
import 'Interface.dart';
import 'FactoryClass.dart';
import 'package:meta/meta.dart';
import 'ConstantClass.dart';

有一種情況例外田巴,加入導(dǎo)入的兩個(gè)包里面有同名的類钠糊,這個(gè)時(shí)候如何區(qū)分,java 是用全路徑來標(biāo)識壹哺,Dart里面可以給這個(gè)包里面所有的類設(shè)置一個(gè)別名

import 'package:lib1/lib1.dart';
import 'package:lib2/lib2.dart' as lib2;  //這里利用as來設(shè)置 別名

// Uses Element from lib1.
Element element1 = Element();

// Uses Element from lib2.
lib2.Element element2 = lib2.Element();

如果你想導(dǎo)入的是一個(gè)包中的部分類

// Import only foo.
import 'package:lib1/lib1.dart' show foo;

// Import all names EXCEPT foo.
import 'package:lib2/lib2.dart' hide foo;

設(shè)置這個(gè)功能的出發(fā)點(diǎn)是可以降低包體積么抄伍??管宵? 不得而知

improt 懶加載

這個(gè)是為了在使用導(dǎo)入的類的時(shí)候才會去載入這個(gè)包截珍,主要是為了提升啟動(dòng)效率

如果需要使用懶加載的功能,請使用deferred as 關(guān)鍵字

import 'package:greetings/hello.dart' deferred as hello;

//需要的時(shí)候調(diào)用別名.loadLibiary方法
Future greet() async {
  await hello.loadLibrary();
  hello.printGreeting();
}

在前面的這段代碼中 await 關(guān)鍵字的作用是暫停程序的運(yùn)行直到包導(dǎo)入完成

  • 延遲庫的常量不是導(dǎo)入文件中的常量箩朴。
    請記住岗喉,在加載延遲庫之前,這些常量不存在隧饼。

  • 您不能在導(dǎo)入文件中使用延遲庫中的類型沈堡。
    相反,請考慮將接口類型移動(dòng)到由延遲庫和導(dǎo)入文件導(dǎo)入的庫燕雁。

  • Dart隱式地將loadLibrary()插入到使用deferred as namespace定義的命名空間中诞丽。loadLibrary()函數(shù)返回Future。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末拐格,一起剝皮案震驚了整個(gè)濱河市僧免,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌捏浊,老刑警劉巖懂衩,帶你破解...
    沈念sama閱讀 216,544評論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異金踪,居然都是意外死亡浊洞,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,430評論 3 392
  • 文/潘曉璐 我一進(jìn)店門胡岔,熙熙樓的掌柜王于貴愁眉苦臉地迎上來法希,“玉大人,你說我怎么就攤上這事靶瘸∩灰啵” “怎么了?”我有些...
    開封第一講書人閱讀 162,764評論 0 353
  • 文/不壞的土叔 我叫張陵怨咪,是天一觀的道長屋剑。 經(jīng)常有香客問我,道長诗眨,這世上最難降的妖魔是什么唉匾? 我笑而不...
    開封第一講書人閱讀 58,193評論 1 292
  • 正文 為了忘掉前任,我火速辦了婚禮匠楚,結(jié)果婚禮上肄鸽,老公的妹妹穿的比我還像新娘卫病。我一直安慰自己,他們只是感情好典徘,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,216評論 6 388
  • 文/花漫 我一把揭開白布蟀苛。 她就那樣靜靜地躺著,像睡著了一般逮诲。 火紅的嫁衣襯著肌膚如雪帜平。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,182評論 1 299
  • 那天梅鹦,我揣著相機(jī)與錄音裆甩,去河邊找鬼。 笑死齐唆,一個(gè)胖子當(dāng)著我的面吹牛嗤栓,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播箍邮,決...
    沈念sama閱讀 40,063評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼茉帅,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了锭弊?” 一聲冷哼從身側(cè)響起堪澎,我...
    開封第一講書人閱讀 38,917評論 0 274
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎味滞,沒想到半個(gè)月后樱蛤,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,329評論 1 310
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡剑鞍,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,543評論 2 332
  • 正文 我和宋清朗相戀三年昨凡,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片蚁署。...
    茶點(diǎn)故事閱讀 39,722評論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡便脊,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出形用,到底是詐尸還是另有隱情就轧,我是刑警寧澤证杭,帶...
    沈念sama閱讀 35,425評論 5 343
  • 正文 年R本政府宣布田度,位于F島的核電站,受9級特大地震影響解愤,放射性物質(zhì)發(fā)生泄漏镇饺。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,019評論 3 326
  • 文/蒙蒙 一送讲、第九天 我趴在偏房一處隱蔽的房頂上張望奸笤。 院中可真熱鬧惋啃,春花似錦、人聲如沸监右。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,671評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽健盒。三九已至绒瘦,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間扣癣,已是汗流浹背惰帽。 一陣腳步聲響...
    開封第一講書人閱讀 32,825評論 1 269
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留父虑,地道東北人该酗。 一個(gè)月前我還...
    沈念sama閱讀 47,729評論 2 368
  • 正文 我出身青樓,卻偏偏與公主長得像士嚎,于是被迫代替她去往敵國和親呜魄。 傳聞我的和親對象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,614評論 2 353

推薦閱讀更多精彩內(nèi)容