Dart構(gòu)造函數(shù)介紹

介紹

因?yàn)镕lutter和Dart語言非常容易上手,很多學(xué)習(xí)Flutter的同學(xué),一般都會(huì)直接寫Flutter頁面,對(duì)Dart語言也是一知半解,包括我自己。

Dart語言和很多現(xiàn)代語言都很類似,但是其構(gòu)造函數(shù),其靈活性,還是比我了解的其它語言要多的,所以在寫構(gòu)造函數(shù)的時(shí)候,要么莫名其妙報(bào)錯(cuò),要么寫的很復(fù)雜,沒有將其精髓掌握。

下面跟大家總結(jié)一下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ù)

使用

在定義自己的構(gòu)造函數(shù)之前,我們會(huì)接觸到構(gòu)造函數(shù)的使用,其用法如下:

var p1 = Point(2, 2); //Dart2中,可以省略構(gòu)造函數(shù)前的new
var p2 = Point.fromJson({'x': 1, 'y': 2});
var p = const ImmutablePoint(2, 2); //常量構(gòu)造函數(shù),用來創(chuàng)建編譯期常量

插播廣告
如果想知道某個(gè)變量屬于哪個(gè)類,可以使用runtimeType:
print('The type of a is ${a.runtimeType}');

定義

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

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

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

2. 普通構(gòu)造函數(shù)

這就是我們普通的構(gòu)造函數(shù),其樣子和其它語言幾乎一樣

class Point {
  num x, y;

  Point(num x, num y) {
    // There's a better way to do this, stay tuned.
    this.x = x;
    this.y = y;
  }
}

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

class Point {
  num x, y;

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

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

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


class Point {
  num x, y;

  Point(this.x, this.y);

  // 命名構(gòu)造函數(shù),新增代碼
  Point.origin() {
    x = 0;
    y = 0;
  }
}

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

4. 構(gòu)造函數(shù)調(diào)用父類構(gòu)造函數(shù)的順序

如果你的類,繼承于父類,那么子類的構(gòu)造函數(shù),勢必要調(diào)用父類的構(gòu)造函數(shù),這時(shí)候就要分兩種情況:

  • Dart語言幫你調(diào)用父類的無參數(shù)構(gòu)造函數(shù)
  • 代碼中顯式調(diào)用父類的構(gòu)造函數(shù)
4.1 默認(rèn)調(diào)用調(diào)用父類的無參數(shù)構(gòu)造函數(shù)

如果你沒有顯式調(diào)用父類的構(gòu)造函數(shù),并且父類有一個(gè)無參數(shù)構(gòu)造函數(shù),那么Dart就會(huì)幫你在子類的構(gòu)造函數(shù)方法體的最前面,調(diào)用父類的無參數(shù)構(gòu)造函數(shù)。當(dāng)然,后面我們會(huì)說道,構(gòu)造函數(shù)分成好幾部分來初始化成員變量,調(diào)用的順序如下:

  • 初始化列表
  • 父類的無參數(shù)構(gòu)造函數(shù)
  • 子類的無參數(shù)構(gòu)造函數(shù)

當(dāng)然,如果父類沒有無參數(shù)構(gòu)造函數(shù),或者Dart這種隱式調(diào)用無法滿足你的要求,那就需要顯式調(diào)用父類的構(gòu)造函數(shù)了

4.2 顯式調(diào)用父類構(gòu)造函數(shù)

顯式調(diào)用父類構(gòu)造函數(shù),應(yīng)該在初始化列表中完成(記得好像在C++中見到過初始化列表?太久了忘記了)

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
}

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

5. 初始化列表

初始化列表的執(zhí)行順序,在整個(gè)構(gòu)造函數(shù)的最前面,它除了可以調(diào)用父類的構(gòu)造函數(shù),還可以在構(gòu)造函數(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)');
}

尤其是初始化那些final修飾的成員變量時(shí),初始化列表很有用,因?yàn)樵诜椒w中,不能給final修飾的成員變量賦值,因?yàn)?strong>在執(zhí)行方法體的時(shí)候,final修飾的成員變量已經(jīng)不能變了。這個(gè)地方很多人犯錯(cuò)。

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

6. 構(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ù)可以傳遞。

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)造函數(shù),沒有方法體,會(huì)在初始化列表中,調(diào)用另一個(gè)構(gòu)造函數(shù)。

7. 常量構(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的。

8. 工廠構(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ù),沒有權(quán)利訪問this

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

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

?著作權(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),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

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

  • 這是16年5月份編輯的一份比較雜亂適合自己觀看的學(xué)習(xí)記錄文檔,今天18年5月份再次想寫文章,發(fā)現(xiàn)簡書還為我保存起的...
    Jenaral閱讀 3,179評(píng)論 2 9
  • Dart重要概念:1,在變量中可以放置的所有東西都是對(duì)象,而每個(gè)對(duì)象都是類的實(shí)例。無論數(shù)字、函數(shù)、和null都是對(duì)...
    哥哥是歐巴Vitory閱讀 939評(píng)論 0 1
  • 此文章是v1.0+時(shí)編寫,年代久遠(yuǎn),小心有毒,謹(jǐn)慎食用?。?! 一些重要概念 所有的東西都是對(duì)象,所有的對(duì)象都是類的...
    soojade閱讀 10,232評(píng)論 2 27
  • importUIKit classViewController:UITabBarController{ enumD...
    明哥_Young閱讀 4,203評(píng)論 1 10
  • 小程序開發(fā)框架的目標(biāo)是通過盡可能簡單、高效的方式讓開發(fā)者可以在微信中開發(fā)具有原生app體驗(yàn)的服務(wù)。 小程序包含一個(gè)...
    李瀟南閱讀 264評(píng)論 0 0

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