前言:樓主平時基本沒有使用過異常處理,因此對異常的認知可能不夠準確,這裏就不翻譯異常的相關內容了,你們能夠去官網自行閱讀介紹,地址 https://dart.dev/guides/language/language-tour#exceptions 。ide
咱們前面提到,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構造等,本人對此不甚理解,所以這裏就不作翻譯,你們有興趣請去官網閱讀相關說明。