Dart Tips

DartPad

DartPad的出現讓人眼前一亮,之後能夠隨時隨地開心的測試一些代碼了,Dart的大部分語言功能DartPad都支持。打開DartPadbash

變量初始化

若是一個對象的引用不侷限於單一的類型,能夠根據設計指南將其指定爲Objectdynamic類型: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]
複製代碼

常量聲明 final 和 const

  • const是編譯時常量,final是運行時常量。兩者都只能被賦值一次。
  • 實例變量能夠是final的但不能夠是const的,final實例變量必須在構造器開始前被初始化,好比在聲明實例變量時初始化,或者做爲構造器參數,或者將其置於構造器的初始化列表中。
  • 若是使用const修飾類中的變量,則必須加上static關鍵字,即static const
  • 沒有使用finalconst修飾的變量的值是能夠被更改的,即便這些變量以前引用過const的值。
var list = const [];
list = [1, 2, 3];
複製代碼
  • Dart2.5以後能夠在定義常量時使用isas......?collection ifcollection 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 和 Setter

全部實例變量均會隱式地聲明一個Getter方法,非final類型的實例變量還會隱式地聲明一個Setter方法。可使用getset關鍵字爲額外的屬性添加GetterSetter方法:

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用來指定前綴解決兩個代碼庫有衝突的狀況。好比若是library1library2都有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();
複製代碼
  • showhide能夠有選擇地導入代碼庫:
// 只導入 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();
}
複製代碼

未完待續

相關文章
相關標籤/搜索