DartPad
的出現讓人眼前一亮,之後能夠隨時隨地開心的測試一些代碼了,Dart
的大部分語言功能DartPad
都支持。打開DartPad。bash
若是一個對象的引用不侷限於單一的類型,能夠根據設計指南將其指定爲Object
或 dynamic
類型:markdown
dynamic name1 = 'Jack'; Object name2 = 'Rose'; 複製代碼
若是一個對象限於單一的類型:async
var name1 = 'Jack'; String name2 = 'Rose'; 複製代碼
局部變量聲明的best practice
是使用var
來作類型被推斷而非使用指定的類型。這樣使用能夠和其餘大部分語言保持一致,提升可讀性。ide
...
和 ...?
將一個 List 中的全部元素插入到另外一個 List 中:函數
var list1 = [1, 2, 3];
var list2 = [0, ...list1];
assert(list2.length == 4);
複製代碼
若是擴展操做符右邊可能爲null
:oop
var list1;
var list2 = [0, ...?list1];
assert(list2.length == 1);
複製代碼
使用Collection If
來建立一個List
:測試
var animals = [ 'Dog', 'Cat', 'Fish', if (canFly) 'Bird' ]; 複製代碼
使用Collection For
將列表中的元素修改後添加到另外一個列表中:ui
var listOfInts = [1, 2, 3]; var listOfStrings = [ 0, for (var i in listOfInts) i*i ]; print(listOfStrings); // [0, 1, 4, 9] 複製代碼
const
是編譯時常量,final
是運行時常量。兩者都只能被賦值一次。final
的但不能夠是const
的,final
實例變量必須在構造器開始前被初始化,好比在聲明實例變量時初始化,或者做爲構造器參數,或者將其置於構造器的初始化列表中。const
修飾類中的變量,則必須加上static
關鍵字,即static const
。final
或const
修飾的變量的值是能夠被更改的,即便這些變量以前引用過const
的值。var list = const [];
list = [1, 2, 3];
複製代碼
Dart2.5
以後能夠在定義常量時使用is
,as
,...
,...?
,collection if
,collection for
。const Object i = 3; const list = [i as int]; const map = {if (i is int) i: "int"}; const set = {if (list is List<int>) ...list}; 複製代碼
{param1, param2, …}
的形式來指定命名參數。調用時須要指定對應的命名,也可使用@required
來標識一個命名參數是必須的參數。使用@required
須要導入package:meta/meta.dart
。void setUserInfo(String name, {@required int age, double height = 0, double weight = 0}) { print('My name is $name, I am $age years old.'); if (height > 0) { print('My height is $height'); } if (weight > 0) { print('My weight is $weight'); } print('\n'); } setUserInfo('Jack', age: 18); setUserInfo('Rose', age: 18, height: 170); 複製代碼
My name is Jack, I am 18 years old.
My name is Rose, I am 18 years old.
My height is 170
複製代碼
[param1, param2, …]
的形式來指定位置參數。調用時需將位置對應起來。void setUserInfo(String name, [int age, double height = 0, double weight = 0]) { print('My name is $name, I am $age years old.'); if (height > 0) { print('My height is $height'); } if (weight > 0) { print('My weight is $weight'); } print('\n'); } setUserInfo('Jack', 18); setUserInfo('Rose', 18, 170, 105); 複製代碼
My name is Jack, I am 18 years old.
My name is Rose, I am 18 years old.
My height is 170
My weight is 105
複製代碼
..
級聯操做並不是一個運算符而是Dart
的特殊語法。this
querySelector('#confirm') // 獲取對象 ..text = 'Confirm' // 使用對象的成員 ..classes.add('important') ..onClick.listen((e) => window.alert('Confirmed!')); 複製代碼
querySelector
返回了一個Selector
對象,後面的級聯操做符都是調用這個Selector
對象的成員並忽略每一個操做的返回值。上面的代碼等價於:spa
var button = querySelector('#confirm'); button.text = 'Confirm'; button.classes.add('important'); button.onClick.listen((e) => window.alert('Confirmed!')); 複製代碼
在返回對象的函數中謹慎使用級聯操做符:
var sb = StringBuffer(); sb.write('foo') ..write('bar'); // (Error: method 'write' isn't defined for 'void'). 複製代碼
上述代碼中的 sb.write() 方法返回的是 void,返回值爲 void 的方法則不能使用級聯運算符。
全部實例變量均會隱式地聲明一個Getter
方法,非final
類型的實例變量還會隱式地聲明一個Setter
方法。可使用get
和set
關鍵字爲額外的屬性添加Getter
和Setter
方法:
class Rectangle { num left, top, width, height; Rectangle(this.left, this.top, this.width, this.height); // 定義兩個計算產生的屬性:right 和 bottom。 num get right => left + width; set right(num value) => left = value - width; num get bottom => top + height; set bottom(num value) => top = value - height; } void main() { var rect = Rectangle(3, 4, 20, 15); assert(rect.left == 3); rect.right = 12; assert(rect.left == -8); } 複製代碼
使用 Getter 和 Setter 的好處是,你能夠先使用你的實例變量,過一段時間過再將它們包裹成方法且不須要改動任何代碼,即先定義後更改且不影響原有邏輯。
abstract
可讓該類成爲抽象類,抽象類將沒法被實例化,經常使用於聲明接口方法。abstract class Animal { void eat(); // 抽象方法。 } class Dog extends Animal { void eat() { print('Dog eat!'); } } 複製代碼
implements
爲隱式接口,每個類都隱式地定義了一個接口並實現了該接口,這個接口包含全部這個類的實例成員以及這個類所實現的其它接口。若是想要建立一個A
類支持調用B
類的API
且不想繼承B
類,則能夠實現B
類的接口。class Point implements Comparable, Location {...}
複製代碼
extends
關鍵字建立一個子類,可以使用super
關鍵字引用一個父類,可使用@override
重寫父類的實例方法。class Television { void turnOn() { } } class SmartTelevision extends Television { void turnOn() { super.turnOn(); } } 複製代碼
class SmartTelevision extends Television { @override void turnOn() { } } 複製代碼
Mixin
是一種在多重繼承中複用某個類中代碼的方法模式。使用with
關鍵字在其後跟上Mixin
類的名字來使用Mixin
模式。Mixin
類繼承自Object
而且不爲該類定義構造函數,可使用關鍵字on
來指定哪些類可使用該Mixin
類。class Musician extends Performer with Musical {
}
class Maestro extends Person with Musical, Aggressive, Demented {
}
複製代碼
mixin MusicalPerformer on Musician {
}
複製代碼
as
用來指定前綴解決兩個代碼庫有衝突的狀況。好比若是library1
和library2
都有Element
類:import 'package:lib1/lib1.dart'; import 'package:lib2/lib2.dart' as lib2; // 使用 lib1 的 Element 類。 Element element1 = Element(); // 使用 lib2 的 Element 類。 lib2.Element element2 = lib2.Element(); 複製代碼
show
和hide
能夠有選擇地導入代碼庫:// 只導入 lib1 中的 foo。(Import only foo). import 'package:lib1/lib1.dart' show foo; // 導入 lib2 中除了 foo 外的全部。 import 'package:lib2/lib2.dart' hide foo; 複製代碼
deferred as
來標識須要延時加載的代碼庫:import 'package:greetings/hello.dart' deferred as hello; 複製代碼
當實際須要使用到庫中API
時先調用loadLibrary
函數加載庫:
Future greet() async {
await hello.loadLibrary();
hello.printGreeting();
}
複製代碼