Dart語法學(xué)習(xí)筆記

1网严、前言:

最近在學(xué)習(xí)Flutter控妻,作為Flutter的編程語言鸥印,Dart語言語法的學(xué)習(xí)自然就編程重中之重。本文主要記錄自己在學(xué)習(xí)Dart語法時(shí)的一些重要概念和學(xué)習(xí)路線蹬音,在學(xué)習(xí)官方文檔時(shí)上煤,對自己覺得重要的或者需要標(biāo)記的語法知識(shí)點(diǎn)進(jìn)行匯總和整理而成,方便后續(xù)進(jìn)行語法整體概念的回顧和復(fù)習(xí)著淆。如果同時(shí)能對其他人有所幫助那就更好不過了劫狠,同時(shí)也建議對Dart感興趣的同學(xué)拴疤,去查看Dart語法的官方文檔。

2独泞、 Important concepts(重要的概念)

  • 所有能夠使用變量引用的都是對象呐矾, 每個(gè)對象都是一個(gè)的實(shí)例。在 Dart 中 甚至連 數(shù)字懦砂、方法和 null 都是對象蜒犯。所有的對象都繼承于 Object類。

  • 使用靜態(tài)類型(例如前面示例中的 num ) 可以更清晰的表明你的意圖荞膘,并且可以讓靜態(tài)分析工具來分析你的代碼罚随, 但這并不是牽制性的。(在調(diào)試代碼的時(shí)候你可能注意到 沒有指定類型的變量的類型為 dynamic羽资。)

  • Dart 在運(yùn)行之前會(huì)先解析你的代碼淘菩。你可以通過使用 類型或者編譯時(shí)常量來幫助 Dart 去捕獲異常以及 讓代碼運(yùn)行的更高效。

  • Dart 支持頂級方法 (例如 main())屠升,同時(shí)還支持在類中定義函數(shù)潮改。 (靜態(tài)函數(shù)和實(shí)例函數(shù))。 你還可以在方法中定義方法 (嵌套方法或者局部方法)弥激。

  • 同樣进陡,Dart 還支持頂級變量,以及 在類中定義變量(靜態(tài)變量和實(shí)例變量)微服。 實(shí)例變量有時(shí)候被稱之為域(Fields)或者屬性(Properties)趾疚。

  • 和 Java 不同的是,Dart 沒有 public以蕴、 protected糙麦、 和 private 關(guān)鍵字。如果一個(gè)標(biāo)識(shí)符以 (_) 開頭丛肮,則該標(biāo)識(shí)符 在庫內(nèi)是私有的赡磅。詳情請參考:庫和可見性。

  • 標(biāo)識(shí)符可以以字母或者 _ 下劃線開頭宝与,后面可以是 其他字符和數(shù)字的組合焚廊。

  • 有時(shí)候 表達(dá)式 expression語句 statement 是有區(qū)別的,所以這種情況我們會(huì)分別指明每種情況习劫。

  • Dart 工具可以指出兩種問題:警告和錯(cuò)誤咆瘟。 警告只是說你的代碼可能有問題, 但是并不會(huì)阻止你的代碼執(zhí)行诽里。 錯(cuò)誤可以是編譯時(shí)錯(cuò)誤也可以是運(yùn)行時(shí)錯(cuò)誤袒餐。遇到編譯時(shí)錯(cuò)誤時(shí),代碼將 無法執(zhí)行;運(yùn)行時(shí)錯(cuò)誤將會(huì)在運(yùn)行代碼的時(shí)候?qū)е乱粋€(gè)異常灸眼。

3卧檐、 Keywords(關(guān)鍵字)

關(guān)鍵字.png
  • 1 帶有上標(biāo) 1 的關(guān)鍵字是 內(nèi)置關(guān)鍵字。避免把內(nèi)置關(guān)鍵字當(dāng)做標(biāo)識(shí)符使用焰宣。 也不要把內(nèi)置關(guān)鍵字 用作類名字和類型名字霉囚。 有些內(nèi)置關(guān)鍵字是為了方便把 JavaScript 代碼移植到 Dart 而存在的。 例如匕积,如果 JavaScript 代碼中有個(gè)變量的名字為 factory佛嬉, 在移植到 Dart 中的時(shí)候,你不必重新命名這個(gè)變量闸天。

  • 2 帶有上標(biāo) 2 的關(guān)鍵字,是在 Dart 1.0 發(fā)布以后又新加的斜做,用于 支持異步相關(guān)的特性苞氮。 你不能在標(biāo)記為 asyncasync*瓤逼、或者 sync* 的方法體內(nèi) 使用 async笼吟、 await、或者 yield 作為標(biāo)識(shí)符霸旗。 詳情請參考:異步支持贷帮。

  • 所以其他單詞都是 保留詞。 你不能用保留詞作為關(guān)鍵字诱告。

4撵枢、Variables(變量)

Default value(默認(rèn)值)
-  未初始化的變量默認(rèn)值為null,數(shù)字也是對象精居,未初始化的數(shù)字默認(rèn)值也為null
- Optional types(可選的類型)
> var name = 'Bob';
> String name = 'Bob'; 

> 即聲明變量時(shí)锄禽,既可以顯式聲明其類型,也可以不聲明其類型靴姿。對于局部變量沃但,推薦使用var,即不指明其類型
Final and const
  • 如果你以后不打算修改一個(gè)變量佛吓,使用 final 或者 const宵晚。 一個(gè) final 變量只能賦值一次;一個(gè) const 變量是編譯時(shí)常量维雇。 (Const 變量同時(shí)也是 final 變量淤刃。) 頂級的 final 變量或者類中的 final 變量在 第一次使用的時(shí)候初始化。
  • 實(shí)例變量可以為 final 但是不能是 const 谆沃。
  • const 關(guān)鍵字不僅僅只用來定義常量钝凶。 有可以用來創(chuàng)建不變的值, 還能定義構(gòu)造函數(shù)為 const 類型的,這種類型 的構(gòu)造函數(shù)創(chuàng)建的對象是不可改變的耕陷。任何變量都可以有一個(gè)不變的值掂名。
// Note: [] creates an empty list.
// const [] creates an empty, immutable list (EIA).
var foo = const [];   // foo is currently an EIA.
final bar = const []; // bar will always be an EIA.
const baz = const []; // baz is a compile-time constant EIA.

// You can change the value of a non-final, non-const variable,
// even if it used to have a const value.
foo = [];

// You can't change the value of a final or const variable.
// bar = []; // Unhandled exception.
// baz = []; // Unhandled exception.

5、Built-in types(內(nèi)置的類型)

Dart 內(nèi)置支持下面這些類型:

  • numbers
  • strings
  • booleans
  • lists (也被稱之為 arrays)
  • maps
  • runes (用于在字符串中表示 Unicode 字符)
  • symbols
Numbers(數(shù)值)
  • int : 整數(shù)值哟沫,其取值通常位于 -253 和 253 之間饺蔑。
  • double : 64-bit (雙精度) 浮點(diǎn)數(shù),符合 IEEE 754 標(biāo)準(zhǔn)嗜诀。
    下面是字符串和數(shù)字之間轉(zhuǎn)換的方式:
// String -> int
var one = int.parse('1');
assert(one == 1);

// String -> double
var onePointOne = double.parse('1.1');
assert(onePointOne == 1.1);

// int -> String
String oneAsString = 1.toString();
assert(oneAsString == '1');

// double -> String
String piAsString = 3.14159.toStringAsFixed(2);
assert(piAsString == '3.14');
Strings(字符串)

可以在字符串中使用表達(dá)式猾警,用法是這樣的: ${expression}

var s = 'string interpolation';

assert('Dart has $s, which is very handy.' ==
       'Dart has string interpolation, ' +
       'which is very handy.');
assert('That deserves all caps. ' +
       '${s.toUpperCase()} is very handy!' ==
       'That deserves all caps. ' +
       'STRING INTERPOLATION is very handy!');

使用三個(gè)單引號或者雙引號也可以 創(chuàng)建多行字符串對象:

var s1 = '''
You can create
multi-line strings like this one.
''';

var s2 = """This is also a
multi-line string.""";

通過提供一個(gè) r 前綴可以創(chuàng)建一個(gè) “原始 raw” 字符串:

var s = r"In a raw string, even \n isn't special.";
Booleans(布爾值)
var name = 'Bob';
if (name) {
  // Prints in JavaScript, not in Dart.
  print('You have a name!');
}

Dart 有一個(gè)名字為 bool 的類型。 只有兩個(gè)對象是布爾類型的:true 和 false 所創(chuàng)建的對象隆敢, 這兩個(gè)對象也都是編譯時(shí)常量发皿。當(dāng) Dart 需要一個(gè)布爾值的時(shí)候,只有 true 對象才被認(rèn)為是 true拂蝎。 所有其他的值都是 flase穴墅。這點(diǎn)和 JavaScript 不一樣,在 JavaScript 中 name 是非 null 對象所以認(rèn)為是 true

Lists(列表)
var list = [1, 2, 3];
assert(list.length == 3);
assert(list[1] == 2);

list[1] = 1;
assert(list[1] == 1);
Maps
var gifts = {
// Keys      Values
  'first' : 'partridge',
  'second': 'turtledoves',
  'fifth' : 'golden rings'
};

var nobleGases = {
// Keys  Values
  2 :   'helium',
  10:   'neon',
  18:   'argon',
};
var gifts = new Map();
gifts['first'] = 'partridge';
gifts['second'] = 'turtledoves';
gifts['fifth'] = 'golden rings';

var nobleGases = new Map();
nobleGases[2] = 'helium';
nobleGases[10] = 'neon';
nobleGases[18] = 'argon';
var gifts = {'first': 'partridge'};
gifts['fourth'] = 'calling birds'; // Add a key-value pair
Runes

在 Dart 中温自,runes 代表字符串的 UTF-32 code points玄货。

Symbols

使用 Symbol 字面量來獲取標(biāo)識(shí)符的 symbol 對象,也就是在標(biāo)識(shí)符 前面添加一個(gè) # 符號:

#radix
#bar

Symbol 字面量定義是編譯時(shí)常量悼泌。

6松捉、Functions(方法)

Dart 是一個(gè)真正的面向?qū)ο笳Z言,方法也是對象并且具有一種 類型馆里, Function隘世。 這意味著,方法可以賦值給變量鸠踪,也可以當(dāng)做其他方法的參數(shù)以舒。 也可以把 Dart 類的實(shí)例當(dāng)做方法來調(diào)用。

bool isNoble(int atomicNumber) {
  return _nobleGases[atomicNumber] != null;
}
isNoble(atomicNumber) {
  return _nobleGases[atomicNumber] != null;
}
bool isNoble(int atomicNumber) => _nobleGases[atomicNumber] != null;
Optional parameters(可選參數(shù))
  • Optional named parameters(可選命名參數(shù))
/// Sets the [bold] and [hidden] flags to the values
/// you specify.
enableFlags({bool bold, bool hidden}) {
  // ...
}
  • Optional positional parameters(可選位置參數(shù))
String say(String from, String msg, [String device]) {
  var result = '$from says $msg';
  if (device != null) {
    result = '$result with a $device';
  }
  return result;
}
assert(say('Bob', 'Howdy', 'smoke signal') ==
    'Bob says Howdy with a smoke signal');
  • Default parameter values(默認(rèn)參數(shù)值)
/// Sets the [bold] and [hidden] flags to the values you
/// specify, defaulting to false.
void enableFlags({bool bold = false, bool hidden = false}) {
  // ...
}

// bold will be true; hidden will be false.
enableFlags(bold: true);
String say(String from, String msg,
    [String device = 'carrier pigeon', String mood]) {
  var result = '$from says $msg';
  if (device != null) {
    result = '$result with a $device';
  }
  if (mood != null) {
    result = '$result (in a $mood mood)';
  }
  return result;
}

assert(say('Bob', 'Howdy') ==
    'Bob says Howdy with a carrier pigeon');
The main() function(入口函數(shù))

沒啥要說的

Functions as first-class objects(一等方法對象)

可以把方法當(dāng)做參數(shù)調(diào)用另外一個(gè)方法慢哈。例如:

printElement(element) {
  print(element);
}

var list = [1, 2, 3];

// Pass printElement as a parameter.
list.forEach(printElement);

方法也可以賦值給一個(gè)變量:

var loudify = (msg) => '!!! ${msg.toUpperCase()} !!!';
assert(loudify('hello') == '!!! HELLO !!!');
Anonymous functions(匿名方法)

下面的代碼定義了一個(gè)參數(shù)為i (該參數(shù)沒有指定類型)的匿名函數(shù)蔓钟。

var list = ['apples', 'oranges', 'grapes', 'bananas', 'plums'];
list.forEach((i) {
  print(list.indexOf(i).toString() + ': ' + i);
});

如果方法只包含一個(gè)語句,可以使用胖箭頭語法縮寫

list.forEach((i) => print(list.indexOf(i).toString() + ': ' + i));
Lexical scope(靜態(tài)作用域)

Lexical closures(詞法閉包)

一個(gè) 閉包 是一個(gè)方法對象卵贱,不管該對象在何處被調(diào)用滥沫, 該對象都可以訪問其作用域內(nèi) 的變量。

/// Returns a function that adds [addBy] to the
/// function's argument.
Function makeAdder(num addBy) {
  return (num i) => addBy + i;
}

main() {
  // Create a function that adds 2.
  var add2 = makeAdder(2);

  // Create a function that adds 4.
  var add4 = makeAdder(4);

  assert(add2(3) == 5);
  assert(add4(3) == 7);
}
Testing functions for equality(測試函數(shù)是否相等)

強(qiáng)調(diào): 是判斷函數(shù)是否相等键俱,不是對象兰绣,這里不再說明。

Return values(返回值)

所有的函數(shù)都返回一個(gè)值编振。如果沒有指定返回值缀辩,則 默認(rèn)把語句 return null; 作為函數(shù)的最后一個(gè)語句執(zhí)行。

7、Operators(操作符)

Arithmetic operators(算術(shù)操作符)
assert(2 + 3 == 5);
assert(2 - 3 == -1);
assert(2 * 3 == 6);
assert(5 / 2 == 2.5);   // Result is a double
assert(5 ~/ 2 == 2);    // Result is an integer
assert(5 % 2 == 1);     // Remainder

print('5/2 = ${5~/2} r ${5%2}'); // 5/2 = 2 r 1
Equality and relational operators(相等相關(guān)的操作符)
assert(2 == 2);
assert(2 != 3);
assert(3 > 2);
assert(2 < 3);
assert(3 >= 3);
assert(2 <= 3);
Type test operators(類型判定操作符)
if (emp is Person) { // Type check
  emp.firstName = 'Bob';
}

(emp as Person).firstName = 'Bob';
Assignment operators(賦值操作符)
a = value;   // 給 a 變量賦值
b ??= value; // 如果 b 是 null臀玄,則賦值給 b瓢阴;
             // 如果不是 null,則 b 的值保持不變
Logical operators(邏輯操作符)

Bitwise and shift operators(位和移位操作符)

Conditional expressions(條件表達(dá)式)
var finalStatus = m.isFinal ? 'final' : 'not final';
Cascade notation (..)(級聯(lián)操作符)
querySelector('#button') // Get an object.
  ..text = 'Confirm'   // Use its members.
  ..classes.add('important')
  ..onClick.listen((e) => window.alert('Confirmed!'));
Other operators(其他操作符)
其他操作符.png

8健无、Control flow statements(流程控制語句)

可以使用下面的語句來控制 Dart 代碼的流程:

  • if and else
  • for loops
  • while and do-while loops
  • break and continue
  • switch and case
  • assert
var callbacks = [];
for (var i = 0; i < 2; i++) {
  callbacks.add(() => print(i));
}
callbacks.forEach((c) => c());
candidates.forEach((candidate) => candidate.interview());

9荣恐、Exceptions(異常)

Throw Catch Finally
distanceTo(Point other) =>
    throw new UnimplementedError();

對于可以拋出多種類型異常的代碼,你可以指定 多個(gè)捕獲語句累贤。每個(gè)語句分別對應(yīng)一個(gè)異常類型叠穆, 如果捕獲語句沒有指定異常類型,則 該可以捕獲任何異常類型:

try {
  breedMoreLlamas();
} on OutOfLlamasException {
  // A specific exception
  buyMoreLlamas();
} on Exception catch (e) {
  // Anything else that is an exception
  print('Unknown exception: $e');
} catch (e) {
  // No specified type, handles all
  print('Something really unknown: $e');
}

如之前代碼所示臼膏,你可以使用on 或者 catch 來聲明捕獲語句硼被,也可以 同時(shí)使用。使用 on 來指定異常類型渗磅,使用 catch 來 捕獲異常對象祷嘶。

try {
  breedMoreLlamas();
} catch(e) {
  print('Error: $e');  // Handle the exception first.
} finally {
  cleanLlamaStalls();  // Then clean up.
}

10、Classes

Instance variables

Constructors

class Point {
  num x;
  num y;

  // Syntactic sugar for setting x and y
  // before the constructor body runs.
  Point(this.x, this.y);
}
Default constructors(默認(rèn)構(gòu)造函數(shù))

如果你沒有定義構(gòu)造函數(shù)夺溢,則會(huì)有個(gè)默認(rèn)構(gòu)造函數(shù)。 默認(rèn)構(gòu)造函數(shù)沒有參數(shù)烛谊,并且會(huì)調(diào)用超類的 沒有參數(shù)的構(gòu)造函數(shù)风响。

Constructors aren’t inherited(構(gòu)造函數(shù)不會(huì)繼承)

子類不會(huì)繼承超類的構(gòu)造函數(shù)。 子類如果沒有定義構(gòu)造函數(shù)丹禀,則只有一個(gè)默認(rèn)構(gòu)造函數(shù) (沒有名字沒有參數(shù))状勤。

Named constructors(命名構(gòu)造函數(shù))

使用命名構(gòu)造函數(shù)可以為一個(gè)類實(shí)現(xiàn)多個(gè)構(gòu)造函數(shù), 或者使用命名構(gòu)造函數(shù)來更清晰的表明你的意圖:

class Point {
  num x;
  num y;

  Point(this.x, this.y);

  // Named constructor
  Point.fromJson(Map json) {
    x = json['x'];
    y = json['y'];
  }
}
  • Invoking a non-default superclass constructor(調(diào)用超類構(gòu)造函數(shù))

構(gòu)造函數(shù)執(zhí)行順序:

initializer list(初始化參數(shù)列表)
superclass’s no-arg constructor(超類的無名構(gòu)造函數(shù))
main class’s no-arg constructor(主類的無名構(gòu)造函數(shù))

class Person {
  String firstName;

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

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

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

  // Prints:
  // in Person
  // in Employee
  if (emp is Person) {
    // Type check
    emp.firstName = 'Bob';
  }
  (emp as Person).firstName = 'Bob';
}
Initializer list(初始化列表)

在構(gòu)造函數(shù)體執(zhí)行之前除了可以調(diào)用超類構(gòu)造函數(shù)之外双泪,還可以 初始化實(shí)例參數(shù)持搜。 使用逗號分隔初始化表達(dá)式。

import 'dart:math';

class Point {
  final num x;
  final num y;
  final num distanceFromOrigin;

  Point(x, y)
      : x = x,
        y = y,
        distanceFromOrigin = sqrt(x * x + y * y);
}

main() {
  var p = new Point(2, 3);
  print(p.distanceFromOrigin);
}
Redirecting constructors(重定向構(gòu)造函數(shù))
class Point {
  num x;
  num y;

  // The main constructor for this class.
  Point(this.x, this.y);

  // Delegates to the main constructor.
  Point.alongXAxis(num x) : this(x, 0);
}
Constant constructors(常量構(gòu)造函數(shù))
class ImmutablePoint {
  final num x;
  final num y;
  const ImmutablePoint(this.x, this.y);
  static final ImmutablePoint origin =
      const ImmutablePoint(0, 0);
}
Factory constructors(工廠方法構(gòu)造函數(shù))
class Logger {
  final String name;
  bool mute = false;

  // _cache is library-private, thanks to the _ in front
  // of its name.
  static final Map<String, Logger> _cache =
      <String, Logger>{};

  factory Logger(String name) {
    if (_cache.containsKey(name)) {
      return _cache[name];
    } else {
      final logger = new Logger._internal(name);
      _cache[name] = logger;
      return logger;
    }
  }

  Logger._internal(this.name);

  void log(String msg) {
    if (!mute) {
      print(msg);
    }
  }
}

var logger = new Logger('UI');
logger.log('Button clicked');

Methods(函數(shù))

  • Instance methods(實(shí)例函數(shù))

  • Getters and setters

  • Abstract methods(抽象函數(shù))

  • Overridable operators(可覆寫的操作符)
class Vector {
  final int x;
  final int y;
  const Vector(this.x, this.y);

  /// Overrides + (a + b).
  Vector operator +(Vector v) {
    return new Vector(x + v.x, y + v.y);
  }

  /// Overrides - (a - b).
  Vector operator -(Vector v) {
    return new Vector(x - v.x, y - v.y);
  }
}

main() {
  final v = new Vector(2, 3);
  final w = new Vector(2, 2);

  // v == (2, 3)
  assert(v.x == 2 && v.y == 3);

  // v + w == (4, 5)
  assert((v + w).x == 4 && (v + w).y == 5);

  // v - w == (0, 1)
  assert((v - w).x == 0 && (v - w).y == 1);
}

Abstract classes(抽象類)

Implicit interfaces(隱式接口)

每個(gè)類都隱式的定義了一個(gè)包含所有實(shí)例成員的接口焙矛, 并且這個(gè)類實(shí)現(xiàn)了這個(gè)接口葫盼。如果你想 創(chuàng)建類 A 來支持 類 B 的 api,而不想繼承 B 的實(shí)現(xiàn)村斟, 則類 A 應(yīng)該實(shí)現(xiàn) B 的接口贫导。

一個(gè)類可以通過 implements 關(guān)鍵字來實(shí)現(xiàn)一個(gè)或者多個(gè)接口, 并實(shí)現(xiàn)每個(gè)接口定義的 API蟆盹。 例如:

// A person. The implicit interface contains greet().
class Person {
  // In the interface, but visible only in this library.
  final _name;

  // Not in the interface, since this is a constructor.
  Person(this._name);

  // In the interface.
  String greet(who) => 'Hello, $who. I am $_name.';
}

// An implementation of the Person interface.
class Imposter implements Person {
  // We have to define this, but we don't use it.
  final _name = "";

  String greet(who) => 'Hi $who. Do you know who I am?';
}

greetBob(Person person) => person.greet('bob');

main() {
  print(greetBob(new Person('kathy')));
  print(greetBob(new Imposter()));
}

Extending a class(擴(kuò)展類)

Enumerated types(枚舉類型)

Adding features to a class: mixins(為類添加新的功能)

Mixins 是一種在多類繼承中重用 一個(gè)類代碼的方法孩灯。
使用 with 關(guān)鍵字后面為一個(gè)或者多個(gè) mixin 名字來使用 mixin。 下面是示例顯示了如何使用 mixin:

class Musician extends Performer with Musical {
  // ...
}

class Maestro extends Person
    with Musical, Aggressive, Demented {
  Maestro(String maestroName) {
    name = maestroName;
    canConduct = true;
  }
}

定義一個(gè)類繼承 Object逾滥,該類沒有構(gòu)造函數(shù)峰档, 不能調(diào)用 super ,則該類就是一個(gè) mixin。例如:

abstract class Musical {
  bool canPlayPiano = false;
  bool canCompose = false;
  bool canConduct = false;

  void entertainMe() {
    if (canPlayPiano) {
      print('Playing piano');
    } else if (canConduct) {
      print('Waving hands');
    } else {
      print('Humming to self');
    }
  }
}

Class variables and methods(類變量和函數(shù))

使用 static 關(guān)鍵字來實(shí)現(xiàn)類級別的變量和函數(shù)讥巡。

Static variables(靜態(tài)變量)

Static methods(靜態(tài)函數(shù))

11掀亩、Generics(泛型)

Generic collections and the types they contain

Dart 的泛型類型是固化的,在運(yùn)行時(shí)有也 可以判斷具體的類型尚卫。例如在運(yùn)行時(shí)(甚至是成產(chǎn)模式) 也可以檢測集合里面的對象類型:

var names = new List<String>();
names.addAll(['Seth', 'Kathy', 'Lars']);
print(names is List<String>); // true
Using generic methods(使用泛型函數(shù))

一開始归榕,泛型只能在 Dart 類中使用。 新的語法也支持在函數(shù)和方法上使用泛型了吱涉。

T first<T>(List<T> ts) {
  // ...Do some initial work or error checking, then...
  T tmp ?= ts[0];
  // ...Do some additional checking or processing...
  return tmp;
}

12刹泄、Libraries and visibility(庫和可見性)

使用 import 和 library 指令可以幫助你創(chuàng)建 模塊化的可分享的代碼。庫不僅僅提供 API怎爵, 還是一個(gè)私有單元:以下劃線 (_) 開頭的標(biāo)識(shí)符只有在庫 內(nèi)部可見特石。每個(gè) Dart app 都是一個(gè)庫, 即使沒有使用 library 命令也是一個(gè)庫鳖链。

Using libraries(使用庫)
import 'package:lib1/lib1.dart';
import 'package:lib2/lib2.dart' as lib2;
// ...
Element element1 = new Element();           // Uses Element from lib1.
lib2.Element element2 = new lib2.Element(); // Uses Element from lib2.
Importing only part of a library(導(dǎo)入庫的一部分)
// Import only foo.
import 'package:lib1/lib1.dart' show foo;

// Import all names EXCEPT foo.
import 'package:lib2/lib2.dart' hide foo;
Lazily loading a library(延遲載入庫)

要延遲加載一個(gè)庫姆蘸,需要先使用 deferred as 來 導(dǎo)入:

import 'package:deferred/hello.dart' deferred as hello;

當(dāng)需要使用的時(shí)候,使用庫標(biāo)識(shí)符調(diào)用 loadLibrary() 函數(shù)來加載庫:

greet() async {
  await hello.loadLibrary();
  hello.printGreeting();
}

在一個(gè)庫上你可以多次調(diào)用 loadLibrary() 函數(shù)芙委。 但是該庫只是載入一次逞敷。

使用延遲加載庫的時(shí)候,請注意一下問題:

  • 延遲加載庫的常量在導(dǎo)入的時(shí)候是不可用的灌侣。 只有當(dāng)庫加載完畢的時(shí)候推捐,庫中常量才可以使用。
  • 在導(dǎo)入文件的時(shí)候無法使用延遲庫中的類型侧啼。 如果你需要使用類型牛柒,則考慮把接口類型移動(dòng)到另外一個(gè)庫中, 讓兩個(gè)庫都分別導(dǎo)入這個(gè)接口庫痊乾。
  • Dart 隱含的把 loadLibrary() 函數(shù)導(dǎo)入到使用 deferred as *的命名空間* 中皮壁。 loadLibrary() 方法返回一個(gè) Future
Implementing libraries(實(shí)現(xiàn)庫)

13哪审、Asynchrony support(異步支持)

checkVersion() async {
  var version = await lookUpVersion();
  if (version == expectedVersion) {
    // Do something.
  } else {
    // Do something else.
  }
}

14蛾魄、Callable classes(可調(diào)用的類)

如果 Dart 類實(shí)現(xiàn)了 call() 函數(shù)則 可以當(dāng)做方法來調(diào)用。
在下面的示例中湿滓,WannabeFunction 類定義了一個(gè) call() 方法畏腕,該方法有三個(gè)字符串參數(shù),并且返回三個(gè)字符串 串聯(lián)起來的結(jié)果茉稠。

class WannabeFunction {
  call(String a, String b, String c) => '$a $b $c!';
}

main() {
  var wf = new WannabeFunction();
  var out = wf("Hi","there,","gang");
  print('$out');
}

15描馅、Isolates

16、Typedefs

在 Dart 語言中而线,方法也是對象铭污。 使用 typedef, 或者 function-type alias 來為方法類型命名恋日, 然后可以使用命名的方法。 當(dāng)把方法類型賦值給一個(gè)變量的時(shí)候嘹狞,typedef 保留類型信息岂膳。

typedef int Compare(Object a, Object b);

class SortedCollection {
  Compare compare;

  SortedCollection(this.compare);
}

 // Initial, broken implementation.
 int sort(Object a, Object b) => 0;

main() {
  SortedCollection coll = new SortedCollection(sort);
  assert(coll.compare is Function);
  assert(coll.compare is Compare);
}

由于 typedefs 只是別名,他們還提供了一種 判斷任意 function 的類型的方法磅网。例如:

typedef int Compare(int a, int b);

int sort(int a, int b) => a - b;

main() {
  assert(sort is Compare); // True!
}

17谈截、Metadata(元數(shù)據(jù))

使用元數(shù)據(jù)給你的代碼添加其他額外信息。 元數(shù)據(jù)注解是以 @ 字符開頭涧偷,后面是一個(gè)編譯時(shí) 常量(例如 deprecated)或者 調(diào)用一個(gè)常量構(gòu)造函數(shù)簸喂。
有三個(gè)注解所有的 Dart 代碼都可以使用: @deprecated、 @override燎潮、 和 @proxy喻鳄。

定義自己的元數(shù)據(jù)注解:

library todo;

class todo {
  final String who;
  final String what;

  const todo(this.who, this.what);
}

使用 @todo 注解的示例:

import 'todo.dart';

@todo('seth', 'make this do something')
void doSomething() {
  print('do something');
}

元數(shù)據(jù)可以在 library、 class确封、 typedef除呵、 type parameter、 constructor爪喘、 factory颜曾、 function、 field秉剑、 parameter泛豪、或者 variable 聲明之前使用,也可以在 import 或者 export 指令之前使用秃症。 使用反射可以在運(yùn)行時(shí)獲取元數(shù)據(jù) 信息。

18吕粹、Comments(注釋)

Single-line comments
Multi-line comments
Documentation comments
/// A domesticated South American camelid (Lama glama).
///
/// Andean cultures have used llamas as meat and pack
/// animals since pre-Hispanic times.
class Llama {
  String name;

  /// Feeds your llama [Food].
  ///
  /// The typical llama eats one bale of hay per week.
  void feed(Food food) {
    // ...
  }

  /// Exercises your llama with an [activity] for
  /// [timeLimit] minutes.
  void exercise(Activity activity, int timeLimit) {
    // ...
  }
}

19种柑、學(xué)習(xí)資料

對Dart感興趣的同學(xué)請查看 Dart官方文檔,進(jìn)行學(xué)習(xí)和參考匹耕。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末聚请,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子稳其,更是在濱河造成了極大的恐慌驶赏,老刑警劉巖,帶你破解...
    沈念sama閱讀 219,539評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件既鞠,死亡現(xiàn)場離奇詭異煤傍,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)嘱蛋,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,594評論 3 396
  • 文/潘曉璐 我一進(jìn)店門蚯姆,熙熙樓的掌柜王于貴愁眉苦臉地迎上來五续,“玉大人,你說我怎么就攤上這事龄恋「砑荩” “怎么了?”我有些...
    開封第一講書人閱讀 165,871評論 0 356
  • 文/不壞的土叔 我叫張陵郭毕,是天一觀的道長它碎。 經(jīng)常有香客問我,道長显押,這世上最難降的妖魔是什么扳肛? 我笑而不...
    開封第一講書人閱讀 58,963評論 1 295
  • 正文 為了忘掉前任,我火速辦了婚禮煮落,結(jié)果婚禮上敞峭,老公的妹妹穿的比我還像新娘。我一直安慰自己蝉仇,他們只是感情好旋讹,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,984評論 6 393
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著轿衔,像睡著了一般沉迹。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上害驹,一...
    開封第一講書人閱讀 51,763評論 1 307
  • 那天鞭呕,我揣著相機(jī)與錄音,去河邊找鬼宛官。 笑死葫松,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的底洗。 我是一名探鬼主播腋么,決...
    沈念sama閱讀 40,468評論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼亥揖!你這毒婦竟也來了珊擂?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,357評論 0 276
  • 序言:老撾萬榮一對情侶失蹤费变,失蹤者是張志新(化名)和其女友劉穎摧扇,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,850評論 1 317
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,002評論 3 338
  • 正文 我和宋清朗相戀三年物延,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片庇绽。...
    茶點(diǎn)故事閱讀 40,144評論 1 351
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡锡搜,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出瞧掺,到底是詐尸還是另有隱情耕餐,我是刑警寧澤,帶...
    沈念sama閱讀 35,823評論 5 346
  • 正文 年R本政府宣布辟狈,位于F島的核電站肠缔,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏哼转。R本人自食惡果不足惜明未,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,483評論 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望壹蔓。 院中可真熱鬧趟妥,春花似錦、人聲如沸佣蓉。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,026評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽勇凭。三九已至疚膊,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間虾标,已是汗流浹背寓盗。 一陣腳步聲響...
    開封第一講書人閱讀 33,150評論 1 272
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留璧函,地道東北人傀蚌。 一個(gè)月前我還...
    沈念sama閱讀 48,415評論 3 373
  • 正文 我出身青樓,卻偏偏與公主長得像蘸吓,于是被迫代替她去往敵國和親善炫。 傳聞我的和親對象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,092評論 2 355