[dart學習]第七篇:類(構造函數)

前言:樓主平時基本沒有使用過異常處理,因此對異常的認知可能不夠準確,這裏就不翻譯異常的相關內容了,你們能夠去官網自行閱讀介紹,地址 https://dart.dev/guides/language/language-tour#exceptionside

咱們前面提到,dart是面向對象的語言,程序中的每一個對象均可以看做是某個類的實例。全部的類都派生自Object類。函數

(一)使用類的成員ui

與C++等面嚮對象語言同樣,dart的類成員包括方法(接口)與數據,使用點號操做符(.)能夠訪問類的方法和數據。看個簡單例子:this

//實例化Point類的一個對象,命名爲p
var p = Point(2, 2);

// 設置類的成員y的值.
p.y = 3;

// 獲取成員y的值
assert(p.y == 3);

// 調用類的distanceTo方法
num distance = p.distanceTo(Point(4, 4));

一個小技巧: 使用 ?. 能夠避免訪問一個空實例,以下例:spa

// If p is non-null, set its y value to 4.
p?.y = 4;

(二)構造器翻譯

瞭解C++的朋友都知道,在C++中類必定有構造函數,dart也是如此。指針

在dart中使用構造器建立一個對象,構造器能夠是ClassName or ClassName.identifier,看如下例子:code

// 使用 ClassName 建立
var p1 = Point(2, 2);
// 使用 ClassName.identifier 建立
var p2 = Point.fromJson({'x': 1, 'y': 2});

也能夠使用 new 關鍵字建立,以下:對象

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

以上兩段代碼的效果是同樣的。blog

(題外話:在C++中使用new建立的是指針,在這裏咱們看到,以上兩段代碼返回都是var類型)

能夠使用const關鍵字建立編譯時常量的對象,簡單例子:

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

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

接着再看以下例子:

var a = const ImmutablePoint(1, 1); // Creates a constant
var b = ImmutablePoint(1, 1); // Does NOT create a constant

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

經過以上兩段代碼咱們能夠看出:即使構造器調用參數徹底相同,const和非const對象也是不等同的。

(三)獲取一個對象的類型

能夠調用對象的 runtimeType 屬性獲取對象的運行時數據類型, 該屬性是 Type 類型的對象。

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

(四)實例變量

先看一個例子:

class Point {
  num x;        // 聲明實例變量x
  num y = 2;  // 聲明實例變量y
}
void main()
{
  var p = Point();        // 構造Point類的實例p
  print("y = ${p.y}");
  if(p.x == null)
  {
    print("p.x == null");
  }
  else
  {
    print("eeee");
  }
}    

代碼運行結果

經過上例咱們能夠看出:類中的變量默認被初始化爲null,若是咱們在類聲明時對變量進行了初始化(如Point類中的y),則該初始化賦值發生在調用構造函數以前

(五)構造函數

咱們能夠經過聲明一個與類名徹底相同的函數來聲明構造函數(和C++同樣),固然,也能夠選擇附加標識符,如 (二)構造器 一段所述。看個例子:

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

 這裏的this關鍵字指當前實例自身,另注:只在名字有衝突的時候才適用this關鍵字,不然能夠省略。

(1)默認構造函數

前面已經提到,和C++同樣,若是你沒有聲明本身的構造函數,那麼編譯器會給你提供一個默認的構造函數,默認構造函數無入參,而且調用父類的無參構造函數。

(2)構造函數不能繼承

子類不能繼承父類的構造函數。前面提到,子類若是沒有聲明構造函數,那麼會有默認的構造函數,而不是集成父類的。

(3) 命名構造函數 (Named constructor)

看個例子:

class Point {
  num x, y;

  Point(this.x, this.y);

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

記住,構造函數不能繼承!若是想用父類中的命名構造函數建立一個子類,那你也必須在子類中實現這個命名構造函數!

(4) 構造函數的調用順序

子類的構造函數中執行的操做順序以下:

初始化列表->父類的無參構造函數->本類的無參構造函數。

若是父類沒有非命名、無參數的構造函數,那麼你就必須手動調用父類的一個構造函數,在分號(:)後指明調用的父類構造函數,看如下例子:

class Person {
  String firstName;

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

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

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

  // Prints:
  // in Person Class
  // in Employee Class
  if (emp is Person) {
    // Type check
    emp.firstName = 'Bob';
    print("emp is Person, firstname = ${emp.firstName}");
  }
  (emp as Person).firstName = 'Bob';
  print("Other,firstname = ${emp.firstName}");
}

以上代碼在vs code中運行結果以下:

父類構造函數的參數中無權限使用this關鍵字!

(5) 重定向構造函數

這個重定向構造函數,我的理解有一點點像C++裏虛基的構造函數,重定向構造函數函數體爲空,僅僅是在該類裏用來重定向其餘的構造函數的。看一個例子:

class Point {
  num x, y;

  // Point類的主構造函數,也是一個重定向構造函數,你看它的函數體是空的
  Point(this.x, this.y);

  // alongXAxis函數被重定向到Point執行構造處理
  Point.alongXAxis(num x) : this(x, 0);
}

(6)其餘

官方對於構造函數還有一些其餘類型的描述,如constant構造、factory構造等,本人對此不甚理解,所以這裏就不作翻譯,你們有興趣請去官網閱讀相關說明。

相關文章
相關標籤/搜索