【Flutter跨端開發】Dart學習筆記二

傳送門:【Flutter跨端開發】Dart學習筆記一

3、函數/方法

3.1、函數也是對象

dart 中函數也是一種對象(類型爲Function),可以賦值給變量也可以當作參數傳遞給其他函數。

String foo() {
  return "foo return";
}

void main() {
  var f = foo;
  print(f());     // 輸出 foo return
}

3.2、函數可以不指定返回值類型

如果不指定函數的返回值類型,系統將識別爲動態類型(無類型)。

foo() {
  return "foo return";
}

String bar() {
  return "bar return";
}

void main() {
  print(foo.runtimeType);   // 輸出 () => dynamic,表示返回值爲 動態類型 的函數
  print(bar.runtimeType);   // 輸出 () => String,表示返回值爲 String類型 的函數
}

3.3、函數的參數

dart 中函數的參數有必要參數可選參數之分,且必要參數必須定義在可選參數前。必要參數和其他語言中的方法參數類似。可選參數使用{}[]定義。

使用{}定義的參數稱爲命名參數,在函數調用時可以不傳參,默認值爲null。但是傳參時必須指定參數名,命名參數也可以爲設爲必須,只需要在參數名前添加required關鍵字。如下例中的bar

使用[]定義的參數爲可選位置參數,在函數調用時可以不傳參,默認值爲null。如下例中的baz

void foo(name, age) {
  print("$name is $age.");
}

void bar({required name, age}) {
  print("$name is $age.");
}

void baz(name, [age]) {
  print("$name is $age.");
}

void main() {
  foo("張三", 18);              // 輸出 張三 is 18.
  foo("張三");                  // 報錯,缺少參數 age
  bar("李四", 18);              // 報錯,命名參數必須指定參數名
  bar(name: "李四", age: 18);   // 輸出 李四 is 18.
  bar(name: "李四");            // 李四 is null.
  baz("王五", 18);              // 王五 is 18.
  baz("王五");                  // 王五 is null.
}

命名參數可選位置參數可以設置默認值,默認值必須是常量值,不可以是變量。

但是必要參數不可以設置默認值(當命名參數標記爲reduired時也不允許設置默認值)。

void foo(name = "張三", age) {    // 報錯,必要參數不能設置默認值
  print("$name is $age.");
}

void bar({name = "李四", age}) {  // 正確
  print("$name is $age.");
}

void baz([name = "王五", age]) {  // 正確
  print("$name is $age.");
}

3.4、匿名函數

你可以創建一個沒有名字的方法,稱之爲 匿名函數Lambda 表達式Closure 閉包

dart 中匿名函數的格式爲:() {}。而在 js 中爲:() => {},在 java/kotlin 中爲:() -> {}

void main() {
  const list = ['apples', 'bananas', 'oranges'];

  list.forEach((item) {
    print('${list.indexOf(item)}: $item');      // 正確, () {} 表示匿名函數
  });

  list.forEach((item) => {
    print('${list.indexOf(item)}: $item');      // 報錯, () => 後只能使用單條語句,不可以使用函數塊
  });

  list.forEach((item) => 
      print('${list.indexOf(item)}: $item')     // 正確, () => 使用單條語句
  );
}

3.5、返回值

所有未聲明爲void的函數都有返回值。沒有顯示返回語句的函數最後一行默認爲執行 return null;

foo() {}

void bar() {}

void main() {
  print(foo.runtimeType);       // 輸出 () => dynamic,表示返回值爲 動態類型 的函數
  print(foo().runtimeType);     // 輸出 null
  print(bar.runtimeType);       // 輸出 () => void,表示沒有返回值的函數
  print(bar().runtimeType);     // 報錯,void函數沒有返回值
}

4、運算符

4.1、算數運算符

/表示除法運算(結果可能含小數),~/表示除法運算並取整。其他運算符與 java 等大多數語言一致。

  print(5 / 2);     // 輸出2.5
  print(5 ~/ 2);    // 輸出2

4.2、類型判斷運算符

as類型轉換,is判斷是否是指定類型,is!判斷是否不是指定類型。

4.3、條件表達式

dart 中的條件表達式條件 ? 表達式1 : 表達式2可以替代if-else語句。表達式1 ?? 表達式2表示當表達式1不爲null時使用表達式1,否則使用表達式2.

  String playerName(String? name) => name ?? 'Guest';

  // 等價於 條件表達式 的格式
  String playerName(String? name) => name != null ? name : 'Guest';

  // 等價於 if-else 的格式
  String playerName(String? name) {
    if (name != null) {
      return name;
    } else {
      return 'Guest';
    }
  }

4.4及聯運算符

級聯運算符 .. ?.. 可以讓你在同一個對象上連續調用多個對象的變量或方法。

  var paint = Paint()
    ..color = Colors.black
    ..strokeCap = StrokeCap.round
    ..strokeWidth = 5.0;

  // 等價於
  var paint = Paint();
  paint.color = Colors.black;
  paint.strokeCap = StrokeCap.round;
  paint.strokeWidth = 5.0;
  querySelector('#confirm')     // 獲取一個可能爲空的對象
    ?..text = 'Confirm'         // 只需在第一次及聯操作時加null判斷
    ..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!'));
  var sb = StringBuffer();
  sb.write('foo')
    ..write('bar');     // 報錯,因爲此處及聯運算的對象爲 write('foo') 的返回值,而不是StringBuffer()。

  // 正確寫法爲
  var sb = StringBuffer()
    ..write('foo')
    ..write('bar');

4.5、其他運算符

?[]表示當list不爲null時訪問list的元素。

?.表示當對象不爲null時訪問對象的成員,與kotlin 的語法類似,es7以上好像也支持了該語法。

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