Flutter學習之Dart語言基礎(構造函數)

最常見的構造函數形式,即生成構造函數,創建一個類的新實例:
class Point {
  num x, y; //Dart中int和double是num的子類

  //this引用當前類對象
  Point(num x, num y) {
    this.x = x;
    this.y = y;
  }
}

使用語法糖的時候可以這樣定義:

class Point {
  num x, y;

  //用於設置x和y的語法糖
  //在構造函數體運行之前
  Point(this.x, this.y);

  @override
  String toString() {
    return ("x: $x, y: $y");
  }
}

//print(new Point(100, 200)); -> 打印 x: 100, y: 200
默認構造函數

如果未聲明構造函數,則會提供默認構造函數。 默認構造函數沒有參數,並在調用父類無參數構造函數。

class Parent{
  Parent(){
    print('In Parent\'s constructor.');
  }
}

class Child extends Parent{
  Child(){
    print('In Child\'s constructor.');
  }
}

//new Child(); -> 打印 In Parent's constructor.  In Child's constructor.
構造函數不能繼承

子類不能繼承其父類構造函數,一個沒有聲明構造函數的子類只有默認(無參數,無名稱)構造函數

命名構造函數

當我們需要定義一個有特別含義的構造函數的時候,可以通過構造函數.XXX來命名構造函數

class Point{
  num x;
  num y;

  Point(this.x, this.y);
  
  //創建一個座標原點類
  Point.origin(){
    this.x = 0;
    this.y = 0;
  }

 //創建一個座標爲(100, 100)的類
 Point.coordinate100(){
    this.x = 100;
    this.y = 100;
  }
  @override
  String toString() {
    return ("x: $x, y: $y");
  }
}
調用父類構造函數

默認情況下,子類中的構造函數調用父類的未命名無參數構造函數。 父類的構造函數在子類構造函數體的開頭被調用。 如果還使用初始化了列表,則會在調用父類構造函數之前執行。 執行順序如下:

  • 初始化列表
  • 父類的無參數構造函數
  • 子類的無參數構造函數

如果父類沒有未命名的無參數構造函數,則必須手動調用父類中的一個構造函數。 在子類的構造函數體之後用冒號(:)指定父類構造函數

例1:默認先調用父類的無參數構造函數

class Parent{
  Parent(){
    print('In Parent\'s constructor.');
  }
}


class Child extends Parent{
  Child(num x, num y) {
    print('In Child\'s constructor.');
  }
}

//new Child(100, 100); -> 打印
//In Parent's constructor.
//In Child's constructor.

例2:手動調用父類其他構造函數

class Parent{
  num x;
  num y;
  Parent(this.x, this.y){
    print('In Parent\'s constructor.');
  }
}

class Child extends Parent{
  Child(num x, num y) : super(x, y){
    print('In Child\'s constructor.');
  }
}

//new Child(100, 100); -> 打印
//In Parent's constructor.
//In Child's constructor.

關於初始化列表:
調用父類構造函數之前,可以在構造函數體執行之前初始化示例變量,用逗號分隔,該過程叫初始化列表。

class Parent{
  num x;
  num y;
  num sum;

  Parent(num px, num py) : x = px, y = py, sum = px + py{
    print("x: $x, y: $y, sum: $sum");
    print('In Parent\'s constructor.');
  }
}

class Child extends Parent{
  Child(num x, num y) : super(x, y){
    print('In Child\'s constructor.');
  }
}

// new Child(100, 100); -> 打印
//x: 100, y: 100, sum: 200
//In Parent's constructor.
//In Child's constructor.
重定向構造函數

有時構造函數需要重定向到同一個類中的另一個構造函數,在冒號後面用this:

class Point {
  num x, y;

  //類的主構造函數
  Point(this.x, this.y);

  //重定向到主構造函數
  Point.alongXAxis(num x) : this(x, 0);
}
常量構造函數

如果你的類需要成爲永遠不會更改的對象,則可以使這些對象成爲編譯時常量。 定義const構造函數要確保所有實例變量都是final。

class Point {
  final num x;
  final num y;
  static final Point2 origin = const Point2(0, 0);

  //const關鍵字放在構造函數名稱之前,且不能有函數體
  const Point2(this.x, this.y);
}

沒有定義final時提示:


使用函數體時提示:


工廠構造函數

在實現不用總是創建新的類對象的時候,可以使用factory關鍵字。 例如,工廠構造函數可能從緩存中返回實例,或者它可能返回子類型的實例:

class Logger {
  final String name;
  bool mute = false;

  //工廠構造函數無法訪問this,所以這裏要用static
  //維護一個緩存的Map對象,
  static final Map<String, Logger> _cache =
      <String, Logger>{};
  
 //調用該構造函數的時候,會從Map中取出對象
  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);
  }
}

//調用
var logger = Logger('UI');
logger.log('Button clicked');
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章