dart系列之:dart類中的構造函數


簡介

dart作為一種面向對象的語言,class是必不可少的。dart中所有的class,除了Null都繼承自Object class。 要想使用dart中的類就要構造類的實例,在dart中,一個類的構造函數有兩種方式,一起來看看吧。

傳統的構造函數

和JAVA一樣,dart中可以使用和class名稱相同的函數作為其構造函數,這也是很多編程語言中首先的構造函數的創建方式,我們以Student類為例,來看看dart中的構造函數是怎么樣的:

class Student {
  int age = 0;
  int id = 0;

  Point(int age, int id) {
    this.age = age;
    this.id = id;
  }
}

上面的this表示的是當前類的實例,對dart來說,this是可以忽略的,但是在上面的例子中,因為類變量的名字和構造函數傳入參數的名字是一樣的,所以需要加上this來進行區分。

上面的代碼雖然很簡單,但是寫起來還是有太多的內容,下面是dart中的一種簡寫方式:

class Student {
  int age = 0;
  int id = 0;

  Student(this.age, this.id);
}

當然,你也可以不指定構造函數,這樣的話dart會為你創建一個默認的無參的構造函數。

命名構造函數

dart和其他語言不同的地方是,還可以使用命名構造函數。命名構造函數的格式是ClassName.identifier,如下所示:


class Student {
  int age = 0;
  int id = 0;

  Student(this.age, this.id);

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

上面的Student.fromJson就是一個命名構造函數。可以使用該構造函數從Map中生成一個Student對象,有點像是java中的工廠方法。

構造函數的執行順序

我們知道,dart中的類是可以繼承的,那么對於dart中的子類來說,其構造函數的執行順序是怎么樣的呢?

如果不給dart類指定構造函數,那么dart會為類自動生成一個無參的構造函數,如果這個類是子類的話,則會自動調用父類的無參構造函數。

那么對應子類的構造函數來說,初始化的時候有三步:

  1. 調用初始化列表
  2. 調用父類的構造函數
  3. 調用自己的構造函數

在步驟2中,如果父類沒有默認的無參構造函數,則需要手動指定具體父類的構造函數。怎么調用呢?可以直接在子類的構造函數后面使用:操作符接父類的構造函數,如下所示:

class Student {
  String? firstName;
  
  Student.fromJson(Map data) {
    print('in Student');
  }
}

class Jone extends Student {
  
  Jone.fromJson(Map data) : super.fromJson(data) {
    print('in Jone');
  }
}

理解了父類的構造函數之后,我們再看一下什么是初始化列表呢?

初始化列表就是在構造函數執行之前執行的代碼,和調用父類的構造函數一樣,也使用:操作符,如下所示:

Point.fromJson(Map<String, double> json)
    : x = json['x']!,
      y = json['y']! {
  print('In Point.fromJson(): ($x, $y)');
}

重定向構造函數

如果一個構造函數需要調用另外一個構造函數,而其本身並不進行任何變動,這可以使用重定向構造函數,重定向構造函數也使用:操作符,后面跟的是另外的構造函數:

class Point {
  double x, y;

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

  // 重定向構造函數
  Point.alongXAxis(double x) : this(x, 0);
}

Constant構造函數

如果對象中的屬性在創建之后,是不會變化的,則可以使用Constant構造函數, 也就是在構造函數前面加上const修飾符,初始化的所有屬性都要以final來修飾:

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

  final double x, y;

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

工廠構造函數

默認情況下,dart類中的構造函數返回的是該類的新實例,但是我們在實際的應用中可能會對返回的對象做些選擇,比如從緩存中返回已經存在的對象,或者返回該類具體的實現子類。

為了實現這樣的功能,dart中專門有一個Factory關鍵字,使用Factory的構造函數叫做工廠構造函數。

class Student {
  final String name;

  static final Map<String, Student> _studentMap =
  <String, Student>{};

  factory Student(String name) {
    return _studentMap.putIfAbsent(
        name, () => Student._newStudent(name));
  }

  factory Student.fromJson(Map<String, Object> json) {
    return Student(json['name'].toString());
  }

  Student._newStudent(this.name);
}

注意,dart中只能有一個未命名的構造函數,對應命名函數來說,名字不能夠重復,否則會報The default constructor is already defined異常。

上面的代碼中,factory Student是一個未命名構造函數,而factory Student.fromJson則是一個命名構造函數。

所以如果你再給Student加一個未命名構造函數,如下:

Student(this.name);

則會報錯。

那么問題來了,factory構造函數和普通構造函數到底有什么區別呢?

他們最大的區別就是普通構造函數是沒有返回值的,而factory構造函數需要一個返回值。

總結

以上就是dart中各種構造函數,和使用過程中需要注意的問題。

本文已收錄於 http://www.flydean.com/06-dart-class/

最通俗的解讀,最深刻的干貨,最簡潔的教程,眾多你不知道的小技巧等你來發現!

歡迎關注我的公眾號:「程序那些事」,懂技術,更懂你!


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM