flutter--Dart基礎語法(一)註釋、變量、數據類型、運算符

一、前言

Flutter 是 Google 開源的 UI 工具包,幫助開發者通過一套代碼庫高效構建多平臺精美應用,Flutter 開源、免費,擁有寬鬆的開源協議,支持移動、Web、桌面和嵌入式平臺。

Flutter是使用Dart語言開發的跨平臺移動UI框架,通過自建繪製引擎,能高性能、高保真地進行Android和IOS開發。Flutter採用Dart語言進行開發,而並非Java,Javascript這類熱門語言,這是Flutter團隊對當前熱門的10多種語言慎重評估後的選擇。因爲Dart囊括了多數編程語言的優點,它更符合Flutter構建界面的方式。

本文主要就是簡單梳理一下Dart語言的一些基礎知識和語法。關於編程語言的基本語法無外乎那麼些內容,註釋、變量、數據類型、運算符、流程控制、函數、類、異常、文件、異步、常用庫等內容,相信大部分讀者都是有一定編程基礎的,所以本文就簡單地進行一個梳理,不做詳細的講解。大家也可以參考 Dart編程語言中文網

二、Dart的基本語法

Dart基本語法是指編寫dart代碼最基本的一些內容、規範,主要包括註釋、變量、數據類型和運算符等內容。

2.1 註釋

Dart 支持單行註釋、多行註釋和文檔註釋。

  • 單行註釋:單行註釋以 // 開始。 所有在 // 和改行結尾之間的內容被編譯器忽略。
    void main() {
      // TODO: refactor into an AbstractLlamaGreetingFactory?
      print('Welcome to my Llama farm!');
    }
  • 多行註釋多行註釋以  /* 開始, 以 */ 結尾。 所有在 /* 和 */ 之間的內容被編譯器忽略 (不會忽略文檔註釋)。 多行註釋可以嵌套。
    void main() {
      /*
       * This is a lot of work. Consider raising chickens.
    
      Llama larry = Llama();
      larry.feed();
      larry.exercise();
      larry.clean();
       */
    }
  • 文檔註釋:文檔註釋可以是多行註釋,也可以是單行註釋, 文檔註釋以 /// 或者 /** 開始。 在連續行上使用 /// 與多行文檔註釋具有相同的效果。在文檔註釋中,除非用中括號括起來,否則Dart 編譯器會忽略所有文本。 使用中括號可以引用類、 方法、 字段、 頂級變量、 函數、 和參數。 括號中的符號會在已記錄的程序元素的詞法域中進行解析。下面是一個引用其他類和成員的文檔註釋,在生成的文檔中,[Food] 會成爲一個鏈接, 指向 Food 類的 API 文檔。
    /// A domesticated South American camelid (Lama glama).
    ///
    /// 自從西班牙時代以來,
    /// 安第斯文化就將駱駝當做肉食類和運輸類動物。
    class Llama {
      String name;
    
      /// 餵養駱駝 [Food].
      ///
      /// 典型的美洲駝每週喫一捆乾草。
      void feed(Food food) {
        // ...
      }
    
      /// 使用 [activity] 訓練駱駝
      /// [timeLimit] 分鐘。
      void exercise(Activity activity, int timeLimit) {
        // ...
      }
    }

2.2 變量

任何保存在變量中的都是一個 對象 , 並且所有的對象都是對應一個  的實例。 無論是數字,函數和 null都是對象。所有對象繼承自Object 類。儘管 Dart 是強類型的,但是 Dart 可以推斷類型,所以類型註釋是可選的。 如果要明確說明不需要任何類型, 需要使用特殊類型 dynamic 。

2.2.1 創建變量

var name = 'Bob';

變量僅存儲對象引用,這裏的變量是 name 存儲了一個 String 類型的對象引用。 “Bob” 是這個 String 類型對象的值。

name 變量的類型被推斷爲 String 。 但是也可以通過指定類型的方式,來改變變量類型。 如果對象不限定爲單個類型,可以指定爲 對象類型 或 動態類型

//指定爲動態類型
dynamic name = 'Bob';
//顯示指定爲字符串類型
String name = 'Bob';

2.2.2 默認值

未初始化的變量默認值是 null。即使變量是數字 類型默認值也是 null,因爲在 Dart 中一切都是對象,數字類型 也不例外。

int lineCount;
assert(lineCount == null); //結果爲true 

提示: 在生產環境代碼中 assert() 函數會被忽略,不會被調用。 在開發過程中, assert(condition) 會在非 true 的條件下拋出異常。

2.3 常量 Final 和 Const

使用過程中從來不會被修改的值,我們成爲常量,可以使用 final 或 const, 而不是 var 或者其他類型。 Final 變量的值只能被設置一次; Const 變量在編譯時就已經固定 (Const 變量 是隱式 Final 的類型.) 。最高級 final 變量或類變量在第一次使用時被初始化。

提示: 實例變量可以是 final 類型但不能是 const 類型。 必須在構造函數體執行之前初始化 final 實例變量 —— 在變量聲明中,參數構造函數中或構造函數的初始化列表中進行初始化。

2.2.1 常量的創建

final name = 'Bob'; // Without a type annotation
final String nickname = 'Bobby';
//final 不能被修改:
name = 'Alice'; // Error: 一個 final 變量只能被設置一次。

如果需要在編譯時就固定變量的值,可以使用 const 類型變量。 如果 Const 變量是類級別的,需要標記爲 static const。 在這些地方可以使用在編譯時就已經固定不變的值,字面量的數字和字符串, 固定的變量,或者是用於計算的固定數字:

const bar = 1000000; // 壓力單位 (dynes/cm2)
const double atm = 1.01325 * bar; // 標準氣壓

// Const 關鍵字不僅可以用於聲明常量變量。 還可以用來創建常量值,以及聲明創建常量值的構造函數。 任何變量都可以擁有常量值。
var foo = const [];
final bar = const []; 
const baz = []; // 聲明 const 的初始化表達式中 const 可以被省略。 比如上面的 baz。  Equivalent to `const []`

//Const 變量的值不可以修改:
baz = [42]; // Error: 常量變量不能賦值修改。

//非 Final , 非 const 的變量是可以被修改的,即使這些變量 曾經引用過 const 值。
foo = [1, 2, 3]; // 曾經引用過 const [] 常量值。

2.2.2 final和const的相同點

1.聲明時必須要賦值

  

2.只能在初始化賦值一次,之後不能重新賦值

3.後面都不能接var關鍵字

4.類型聲明可以忽略,類似 var,可以根據初始化的值推斷出變量類型

2.2.3 final和const的區別

1、final變量的初始值可以在編譯時確定,也可以在運行時確定,cosnt變量的初始值只能是編譯時確定的值,比如當前時間

2.const變量的不可變性是嵌套的,final不是

const a = {'c': 1};
a['c'] = 2;
// 運行結果 Unsupported operation: Cannot set value in unmodifiable Map

3.內存中的創建:相同的值,final變量會重複創建,const會引用同一份值

  const a = {'c': 1};
  const b = {'c': 1};
  print(a == b);//true
  final c = {'c': 1};
  final d = {'c': 1};
  print(c == d);//false

2.4 數據類型

Dart 語言支持以下內建類型:

  • Number:數值類型
  • String:字符串類型
  • Boolean:布爾類型
  • List (也被稱爲 Array):列表或數組類型
  • Map:字典類型
  • Set:集合類型
  • Rune (用於在字符串中表示 Unicode 字符):
  • Symbol:符號類型

這些類型都可以被初始化爲字面量。 例如, 'this is a string' 是一個字符串的字面量, true 是一個布爾的字面量。因爲在 Dart 所有的變量終究是一個對象(一個類的實例), 所以變量可以使用 構造涵數 進行初始化。 一些內建類型擁有自己的構造函數。 例如, 通過 Map() 來構造一個 map 變量。

2.4.1 Number

Dart 語言的 Number 有兩種類型:

  • int:整數值不大於64位, 具體取決於平臺。 在 Dart VM 上, 值的範圍從 -263到 263 - 1. Dart 被編譯爲 JavaScript 時,使用 JavaScript numbers, 值的範圍從 -253 到 253 - 1.
  • double:64位(雙精度)浮點數,依據 IEEE 754 標準。

int 和 double 都是 num. 的亞類型。 num 類型包括基本運算 +, -, /, 和 *, 以及 abs() ceil(), 和 floor(), 等函數方法。 (按位運算符,例如»,定義在 int 類中。) 如果 num 及其亞類型找不到你想要的方法, 嘗試查找使用 dart:math 庫。

// 整數類型不包含小數點。 下面是定義整數類型字面量的例子:
var x = 1;
var hex = 0xDEADBEEF;

// 如果一個數字包含小數點,那麼就是小數類型。 下面是定義小數類型字面量的例子: var y = 1.1; var exponents = 1.42e5;
// 從 Dart 2.1 開始,必要的時候 int 字面量會自動轉換成 double 類型。 double z = 1; // 相當於 double z = 1.0. //版本提示: 在dart 2.1 之前,在 double 上下文中使用 int 字面量是錯誤的。 //以下是將字符串轉換爲數字的方法,反之亦然: // 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');
//int 特有的傳統按位運算操作,移位(<<, >>),按位與(&)以及 按位或(|)。 例如: assert((3 << 1) == 6); // 0011 << 1 == 0110 assert((3 >> 1) == 1); // 0011 >> 1 == 0001 assert((3 | 4) == 7); // 0011 | 0100 == 0111

//數字類型字面量是編譯時常量。 在算術表達式中,只要參與計算的因子是編譯時常量, 那麼算術表達式的結果也是編譯時常量。 const msPerSecond = 1000; const secondsUntilRetry = 5; const msUntilRetry = secondsUntilRetry * msPerSecond;

2.4.2 String

Dart 字符串是一組 UTF-16 單元序列。 字符串通過單引號或者雙引號創建。

var s1 = 'Single quotes work well for string literals.';
var s2 = "Double quotes work just as well.";
var s3 = 'It\'s easy to escape the string delimiter.';
var s4 = "It's even easier to use the other delimiter.";

字符串可以通過 ${expression} 的方式內嵌表達式。 如果表達式是一個標識符,則 {} 可以省略。 在 Dart 中通過調用就對象的 toString() 方法來得到對象相應的字符串。

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

提示: == 運算符用來測試兩個對象是否相等。 在字符串中,如果兩個字符串包含了相同的編碼序列,那麼這兩個字符串相等。

此外,還有字符串的拼接和多行字符串等用法

// 用 + 運算符來把多個字符串連接爲一個,也可以把多個字面量字符串寫在一起來實現字符串連接:
var s1 = 'String '
    'concatenation'
    " works even over line breaks.";
assert(s1 ==
    'String concatenation works even over '
    'line breaks.');

var s2 = 'The + operator ' + 'works, as well.';
assert(s2 == 'The + operator works, as well.'); 


// 使用連續三個單引號或者三個雙引號實現多行字符串對象的創建: var s1 = ''' You can create multi-line strings like this one. '''; var s2 = """This is also a multi-line string.""";

// 使用 r 前綴,可以創建 “原始 raw” 字符串: var s = r"In a raw string, even \n isn't special.";

**一個編譯時常量的字面量字符串中,如果存在插值表達式,表達式內容也是編譯時常量, 那麼該字符串依舊是編譯時常量。 插入的常量值類型可以是 null,數值,字符串或布爾值

// const 類型數據
const aConstNum = 0;
const aConstBool = true;
const aConstString = 'a constant string';

// 非 const 類型數據
var aNum = 0;
var aBool = true;
var aString = 'a string';
const aConstList = [1, 2, 3];

const validConstString = '$aConstNum $aConstBool $aConstString'; //const 類型數據
// const invalidConstString = '$aNum $aBool $aString $aConstList'; //非 const 類型數據,error Not a constant expression.

2.4.3 Boolean

Dart 使用 bool 類型表示布爾值。 Dart 只有字面量 true、false 是布爾類型, 這兩個對象都是編譯時常量。

Dart 的類型安全意味着不能使用 if (nonbooleanValue) 或者 assert (nonbooleanValue)。 而是應該像下面這樣,明確的進行值檢查:

// 檢查空字符串。
var fullName = '';
assert(fullName.isEmpty);

// 檢查 0 值。
var hitPoints = 0;
assert(hitPoints <= 0);

// 檢查 null 值。
var unicorn;
assert(unicorn == null);

// 檢查 NaN 。
var iMeantToDoThis = 0 / 0;
assert(iMeantToDoThis.isNaN);

2.4.4 List

幾乎每種編程語言中最常見的集合可能是 array 或有序的對象集合。 在 Dart 中的 Array 就是 List 對象, 通常稱之爲 List 。 下面是一個 Dart List 的示例:

var list = [1, 2, 3];

提示: Dart 推斷 list 的類型爲 List<int> 。 如果嘗試將非整數對象添加到此 List 中, 則分析器或運行時會引發錯誤。 

Lists 的下標索引從 0 開始,第一個元素的索引是 0。 list.length - 1 是最後一個元素的索引。 

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

list[1] = 1;
assert(list[1] == 1);

//在 List 字面量之前添加 const 關鍵字,可以定義 List 類型的編譯時常量
var constantList = const [1, 2, 3];
// constantList[1] = 1; // 取消註釋會引起錯誤。

List 類型包含了很多 List 的操作函數。 更多信息參考 泛型 和 集合.

2.4.5 Set

在 Dart 中 Set 是一個元素唯一且無序的集合。 Dart 爲 Set 提供了 Set 字面量和 Set 類型。

版本提示: 雖然 Set 類型 一直是 Dart 的核心部分, 但在 Dart2.2 中才引入了 Set 字面量 。

下面是通過字面量創建 Set 的一個簡單示例:

var halogens = {'fluorine', 'chlorine', 'bromine', 'iodine', 'astatine'};

Note: Dart 推斷 halogens 類型爲 Set<String> 。如果嘗試爲它添加一個 錯誤類型的值,分析器或執行時會拋出錯誤。

要創建一個空集,使用前面帶有類型參數的 {} ,或者將 {} 賦值給 Set 類型的變量:

var names = <String>{};
// Set<String> names = {}; // 這樣也是可以的。
// var names = {}; // 這樣會創建一個 Map ,而不是 Set 。

是 Set 還是 Map ? Map 字面量語法同 Set 字面量語法非常相似。 因爲先有的 Map 字母量語法,所以 {} 默認是 Map 類型。   如果忘記在 {} 上註釋類型或賦值到一個未聲明類型的變量上,   那麼 Dart 會創建一個類型爲 Map<dynamic, dynamic> 的對象。

// 使用 add() 或 addAll() 爲已有的 Set 添加元素:
var elements = <String>{};
elements.add('fluorine');
elements.addAll(halogens);

// 使用 .length 來獲取 Set 中元素的個數:
var elements = <String>{};
elements.add('fluorine');
elements.addAll(halogens);
assert(elements.length == 5);

// 在 Set 字面量前增加 const ,來創建一個編譯時 Set 常量:
final constantSet = const {
  'fluorine',
  'chlorine',
  'bromine',
  'iodine',
  'astatine',
};
// constantSet.add('helium'); // Uncommenting this causes an error.

更多關於 Set 的內容,參閱 Generic 及 Set

2.4.6 Map

通常來說, Map 是用來關聯 keys 和 values 的對象。 keys 和 values 可以是任何類型的對象。在一個 Map 對象中一個 key 只能出現一次。 但是 value 可以出現多次。 Dart 中 Map 通過 Map 字面量 和 Map 類型來實現。下面是使用 Map 字面量的兩個簡單例子:

var gifts = {
  // Key:    Value
  'first': 'partridge',
  'second': 'turtledoves',
  'fifth': 'golden rings'
};

var nobleGases = {
  2: 'helium',
  10: 'neon',
  18: 'argon',
};

提示: Dart 會將 gifts 的類型推斷爲 Map<String, String>, nobleGases 的類型推斷爲 Map<int, String> 。 如果嘗試在上面的 map 中添加錯誤類型,那麼分析器或者運行時會引發錯誤。

以上 Map 對象也可以使用 Map 構造函數創建:

var gifts = Map();
gifts['first'] = 'partridge';
gifts['second'] = 'turtledoves';
gifts['fifth'] = 'golden rings';

var nobleGases = Map();
nobleGases[2] = 'helium';
nobleGases[10] = 'neon';
nobleGases[18] = 'argon';

提示: 這裏爲什麼只有 Map() ,而不是使用 new Map()。 因爲在 Dart 2 中,new 關鍵字是可選的。 

// 添加 key-value 對到已有的 Map 中:
var gifts = {'first': 'partridge'};
gifts['fourth'] = 'calling birds'; // Add a key-value pair

// 從一個 Map 中獲取一個 value:
var gifts = {'first': 'partridge'};
assert(gifts['first'] == 'partridge');

// 如果 Map 中不包含所要查找的 key,那麼 Map 返回 null:
var gifts = {'first': 'partridge'};
assert(gifts['fifth'] == null);

// 使用 .length 函數獲取當前 Map 中的 key-value 對數量:
var gifts = {'first': 'partridge'};
gifts['fourth'] = 'calling birds';
assert(gifts.length == 2);

// 創建 Map 類型運行時常量,要在 Map 字面量前加上關鍵字 const。
final constantMap = const {
  2: 'helium',
  10: 'neon',
  18: 'argon',
};

// constantMap[2] = 'Helium'; // 取消註釋會引起錯誤。

更名多關於 Map 的內容,參考 Generics and Maps.

2.4.7 Rune

在 Dart 中, Rune 用來表示字符串中的 UTF-32 編碼字符

Unicode 定義了一個全球的書寫系統編碼, 系統中使用的所有字母,數字和符號都對應唯一的數值編碼。 由於 Dart 字符串是一系列 UTF-16 編碼單元, 因此要在字符串中表示32位 Unicode 值需要特殊語法支持。

表示 Unicode 編碼的常用方法是, \uXXXX, 這裏 XXXX 是一個4位的16進制數。 例如,心形符號 (♥) 是 \u2665。 對於特殊的非 4 個數值的情況, 把編碼值放到大括號中即可。 例如,emoji 的笑臉 (�) 是 \u{1f600}

String 類有一些屬性可以獲得 rune 數據。 屬性 codeUnitAt 和 codeUnit 返回16位編碼數據。 屬性 runes 獲取字符串中的 Rune 。

下面是示例演示了 Rune 、 16-bit code units、 和 32-bit code points 之間的關係。 

main() {
  var clapping = '\u{1f44f}';
  print(clapping);
  print(clapping.codeUnits);
  print(clapping.runes.toList());

  Runes input = new Runes(
      '\u2665  \u{1f605}  \u{1f60e}  \u{1f47b}  \u{1f596}  \u{1f44d}');
  print(new String.fromCharCodes(input));
}

提示: 謹慎使用 list 方式操作 Rune 。 這種方法很容易引發崩潰, 具體原因取決於特定的語言,字符集和操作。

2.4.8 Symbol

一個 Symbol 對象表示 Dart 程序中聲明的運算符或者標識符。 你也許永遠都不需要使用 Symbol ,但要按名稱引用標識符的 API 時, Symbol 就非常有用了。 因爲代碼壓縮後會改變標識符的名稱,但不會改變標識符的符號。 通過字面量 Symbol ,也就是標識符前面添加一個 # 號,來獲取標識符的 Symbol 。

#radix
#bar

Symbol 字面量是編譯時常量。

2.5 運算符

下表是 Dart中定義的運算符,描述的運算符優先級近似於Dart 解析器實際行爲。

描述運算符
前綴運算符 expr++    expr--    ()    []    .    ?.
後綴運算符 -expr    !expr    ~expr    ++expr    --expr   
倍數運算符 *    /    %  ~/
加減運算符 +    -
移位運算符 <<    >>    >>>
位與 &
位異或 ^
位或 |
關係運算符和測試運算符 >=    >    <=    <    as    is    is!
相等判斷 ==    !=   
邏輯與 &&
邏輯或 ||
判空運算符 ??
條件運算符 expr1 ? expr2 : expr3
級聯運算符 ..
賦值運算符 =    *=    /=   +=   -=   &=   ^=   etc.

創建表達式的時候會用到運算符。 下面是一些運算符表達式的實例:

a++
a + b
a = b
a == b
c ? a : b
a is T

在 運算符表 中, 每一行的運算符優先級,由上到下依次排列,第一行優先級最高,最後一行優先級最低。 例如 %運算符優先級高於 == , 而 == 高於 &&。 根據優先級規則,那麼意味着以下兩行代碼執行的方式相同:

// 括號可以提高可讀性。
if ((n % i == 0) && (d % i == 0)) ...

// 可讀性差,但是是等效的。
if (n % i == 0 && d % i == 0) ... 

警告: 對於有兩個操作數的運算符,運算符的功能由左邊的操作數決定。 例如, 如果有兩個操作數 Vector 和 Point, aVector + aPoint 使用的是 Vector 中定義的 + 運算符。

下面就對dart中的運算符進行常規意義的分類簡單列舉一下:

  • 算術運算符:+、-、*、/、~/(整除,結果爲整數)、%(求餘運算)、++(自增)、--(自減)。(++、--分別有前綴和後綴兩種表達形式,大家在學習的過程中要注意他們之間的區別)
    assert(2 + 3 == 5);
    assert(2 - 3 == -1);
    assert(2 * 3 == 6);
    assert(5 / 2 == 2.5); // 結果是雙浮點型
    assert(5 ~/ 2 == 2); // 結果是整型
    assert(5 % 2 == 1); // 餘數
    
    assert('5/2 = ${5 ~/ 2} r ${5 % 2}' == '5/2 = 2 r 1');
  • 關係運算符:==、!=、>、<、>=、<=,都是常規符號,不做其他解釋,大家要注意的是關係運算符的表達式結果爲boolean類型。
    assert(2 == 2);
    assert(2 != 3);
    assert(3 > 2);
    assert(2 < 3);
    assert(3 >= 3);
    assert(2 <= 3);
  • 邏輯運算符:&&(邏輯與,短路運算)、||(邏輯或,短路運算)、!。
    //短路運算,即當左邊的表達式結果能確定最終結果時,右邊的表達式不再進行運算
      var a = 10;
      var b = a > 9 || a++ > 10; //a>9成立,又是或運算,所以b的結果爲true,右邊的 a++ > 10不會進行計算,所以a的值不會加1
      print(a); //10
  • 賦值運算符:=、+=、-=、*=、/=。。。等一系列的擴展賦值運算符
    var a = 2; // 使用 = 複製
    a *= 3; // 複製並做乘法運算: a = a * 3
    assert(a == 6);
  • 位運算符:&(按位與運算)、|(按位或運算)、^(按位異或運算)、<<(按位左移)、>>(按位右移)。(所有的位運算都是以二進制形式進行的)
    final value = 0x22;
    final bitmask = 0x0f;
    
    assert((value & bitmask) == 0x02); // AND
    assert((value & ~bitmask) == 0x20); // AND NOT
    assert((value | bitmask) == 0x2f); // OR
    assert((value ^ bitmask) == 0x2d); // XOR
    assert((value << 4) == 0x220); // Shift left
    assert((value >> 4) == 0x02); // Shift right
  • 條件運算符:
    •  condition ? expr1 : expr2 如果條件爲 true, 執行 expr1 (並返回它的值), 否則, 執行並返回 expr2 的值。
    •  expr1 ?? expr2 如果 expr1 是 non-null, 返回 expr1 的值; 否則, 執行並返回 expr2 的值。
  • 級聯運算符(..):可以實現對同一個對像進行一系列的操作。 除了調用函數, 還可以訪問同一對象上的字段屬性。 這通常可以節省創建臨時變量的步驟, 同時編寫出更流暢的代碼。嚴格的來講, “兩個點” 的級聯語法不是一個運算符。 它只是一個 Dart 的特殊語法。
    // 第一句調用函數 querySelector() , 返回獲取到的對象。 獲取的對象依次執行級聯運算符後面的代碼, 代碼執行後的返回值會被忽略。
    querySelector('#confirm') // 獲取對象。
      ..text = 'Confirm' // 調用成員變量。
      ..classes.add('important')
      ..onClick.listen((e) => window.alert('Confirmed!'));
    
    // 上面的代碼等價於:
    var button = querySelector('#confirm');
    button.text = 'Confirm';
    button.classes.add('important');
    button.onClick.listen((e) => window.alert('Confirmed!'));
    
    // 級聯運算符可以嵌套,例如:
    final addressBook = (AddressBookBuilder()
          ..name = 'jenny'
          ..email = '[email protected]'
          ..phone = (PhoneNumberBuilder()
                ..number = '415-555-0100'
                ..label = 'home')
              .build())
        .build();
    
    // 在返回對象的函數中謹慎使用級聯操作符。 例如,下面的代碼是錯誤的:
    var sb = StringBuffer();
    sb.write('foo')
      ..write('bar'); // Error: 'void' 沒喲定義 'write' 函數。
    // sb.write() 函數調用返回 void, 不能在 void 對象上創建級聯操作。
  • 類型判定運算符:as()、is(判定是否是指定類型或該類型子類的對象)、is! (跟is相反)。
    • 使用 as 運算符將對象強制轉換爲特定類型。 通常,可以認爲是 is 類型判定後,被判定對象調用函數的一種縮寫形式。 請考慮以下代碼: 
if (emp is Person) {
  // 類型判斷
  // emp.firstName = 'Bob';

  // 下面這種寫法一般是沒問題的,進行類型強轉
  (emp as Person).firstName = 'Bob';
}

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章