Dart語法摘要(二)

學(xué)Flutter就和學(xué)iOS一樣,先學(xué)基本語言語法的使用,再學(xué)習(xí)搭UI,iOS是OC和Swift,F(xiàn)lutter么就是Dart,語言學(xué)多了語法都差球不多,特別是這些新的語言,很多東西都是相似的,但是長時(shí)間不用容易忘記,與其每次去網(wǎng)上瞎jb找,不如自己總結(jié)一些,以后看自己寫的東西就行了。文中個(gè)別結(jié)論是我自己總結(jié)出來的,不能保證準(zhǔn)確性,看到的同學(xué)僅供參考。

本章提綱:
1.函數(shù)
2.函數(shù)的參數(shù)
3.匿名函數(shù)
4.運(yùn)算符

函數(shù)

1.Dart也是面向?qū)ο笳Z言,所以即使函數(shù)也是對象,所有也有類型,函數(shù)的類型就Function,這個(gè)和Swift中一樣的哇,函數(shù)都是一等公民,意味著你可以將函數(shù)作為變量定義或者作為其他函數(shù)的參數(shù)或者返回值。如果函數(shù)中只有一個(gè)表達(dá)式,那么可以使用箭頭語法(arrow syntax)。

//定義一個(gè)函數(shù)
int sum(num num1, num num2) {
  return num1 + num2;
}
//省略返回值的類型依然是可以的
sum(num num1, num num2) {
  return num1 + num2;
}
//注意,這里面只能是一個(gè)表達(dá)式,不能是一個(gè)語句
sum(num1, num2) => num1 + num2;

函數(shù)的參數(shù)

1.函數(shù)的參數(shù)可以分成兩類: 必須參數(shù)可選參數(shù),必須參數(shù)么就是函數(shù)基本的參數(shù),可選參數(shù)可以分為命名可選參數(shù)位置可選參數(shù)

// 命名可選參數(shù),age和height就是可選參數(shù)
printInfo1(String name, {int age, double height}) {
  print('name=$name age=$age height=$height');
}

// 調(diào)用printInfo1函數(shù)
printInfo1('tong'); // name= tong age=null height=null
printInfo1('tong', age: 18); // name= tong age=18 height=null
printInfo1('tong', age: 18, height: 1.88); // name= tong age=18 height=1.88
printInfo1('tong', height: 1.88); // name= tong age=null height=1.88

2.命名可選參數(shù), 可以指定某個(gè)參數(shù)是必傳的,使用@required標(biāo)記,這點(diǎn)在第一次看的時(shí)候不是很理解,因?yàn)榧热皇强蛇x參數(shù)了,為啥又可以要求必傳,要求必傳直接設(shè)為必傳參數(shù)不就行了,這兩者感覺有點(diǎn)矛盾,后來看官方很多類里面都這么用的,目前還沒體會(huì)到這種用法的優(yōu)勢在哪。

補(bǔ)充:看到后面官方文檔有個(gè)解釋我覺得還算能說的過去,就是為啥不用必傳參數(shù)是因?yàn)樵贔lutter里很多widget的屬性很多,如果用必傳參數(shù)調(diào)用的時(shí)候看不到方法名,不知道傳的是哪個(gè)參數(shù),而使用命名可選+@requierd就可以實(shí)現(xiàn)既可以看到方法名,方便外部調(diào)用,也可以有必傳參數(shù)的限制了,更多的是方便使用。

intInfo3(String name, {int age, double height, @required String address}) {
  print('name=$name age=$age height=$height address=$address');
}

3.位置可選參數(shù),調(diào)用的時(shí)候參數(shù)的順序不能調(diào)換。

// 定義位置可選參數(shù)
printInfo2(String name, [int age, double height]) {
  print('name=$name age=$age height=$height');
}

// 調(diào)用printInfo2函數(shù)
printInfo2('why'); // name=why age=null height=null
printInfo2('why', 18); // name=why age=18 height=null
printInfo2('why', 18, 1.88); // name=why age=18 height=1.88

4.可選參數(shù)默認(rèn)值

// 參數(shù)的默認(rèn)值
printInfo4(String name, {int age = 18, double height=1.88}) {
  print('name=$name age=$age height=$height');
}

函數(shù)是一等公民

上面說過了,可以把函數(shù)當(dāng)做其他類型的變量一樣在各個(gè)場合使用。

main(List<String> args) {
  // 1.將函數(shù)賦值給一個(gè)變量
  var bar = foo;
  print(bar);

  // 2.將函數(shù)作為另一個(gè)函數(shù)的參數(shù)
  test(foo);

  // 3.將函數(shù)作為另一個(gè)函數(shù)的返回值
  var func =getFunc();
  func('tong');
}

// 1.定義一個(gè)函數(shù)
foo(String name) {
  print('傳入的name:$name');
}

// 2.將函數(shù)作為另外一個(gè)函數(shù)的參數(shù)
test(Function func) {
  func('tong');
}

// 3.將函數(shù)作為另一個(gè)函數(shù)的返回值
Function getFunc() {
  return foo;
}

匿名函數(shù)

沒有名字的函數(shù)又稱為匿名函數(shù),也可以叫l(wèi)ambda或者closure,這玩意兒基本每種語言里都有,叫法不一樣,OC叫block,原理都差不多。

main(List<String> args) {
  // 1.定義數(shù)組
  var movies = ['西游記', '東游記', '南游記', '北游記'];

  // 2.使用forEach遍歷: 有名字的函數(shù)
  printElement(item) {
    print(item);
  }
  movies.forEach(printElement);

  // 3.使用forEach遍歷: 匿名函數(shù)
  movies.forEach((item) {
    print(item);
  });
  movies.forEach((item) => print(item));
}

函數(shù)返回值

所有函數(shù)都返回一個(gè)值。如果沒有指定返回值,則隱式返回null附加到函數(shù)體。

運(yùn)算符

基本的+-*/和其他語言一樣,主要記錄一下Dart特有的幾個(gè)運(yùn)算符。
1.整除運(yùn)算~/

var num = 7;
print(num ~/ 3); // 整除操作, 結(jié)果2;

2.??=賦值操作
當(dāng)變量為null時(shí),使用后面的內(nèi)容進(jìn)行賦值。當(dāng)變量有值時(shí),使用自己原來的值。

main(List<String> args) {
  // var name2 = 'tong';
  var name2 = null;
  name2 ??= 'chao'; 
  print(name2); // 當(dāng)name2初始化為tong時(shí),結(jié)果為tong,當(dāng)初始化為null時(shí),賦值了chao
}

3.條件運(yùn)算符??
expr1 ?? expr2,如果expr1null,則返回expr2的結(jié)果;如果expr1不是null,直接使用expr1的結(jié)果。

var temp = 'why';
var temp = null;
var name = temp ?? 'kobe';
print(name);

4.級聯(lián)語法:..
可以對一個(gè)對象進(jìn)行連續(xù)的操作。除了調(diào)用函數(shù),還可以訪問同一對象上的字段屬性。 這通??梢怨?jié)省創(chuàng)建臨時(shí)變量的步驟,同時(shí)編寫出更流暢的代碼。

main(List<String> args) {
  final p1 = Person();
  p1.name = 'tong';
  p1.run();
  p1.eat();
  p1.swim();

  //級聯(lián)語法
  final p2 = Person()
              ..name = "tong"
              ..run()
              ..eat()
              ..swim();
}

5.類型判定運(yùn)算符
as,is,和 is! 運(yùn)算符用于在運(yùn)行時(shí)處理類型檢查。is運(yùn)算符判斷對象是否為某種類型,as 運(yùn)算符將對象強(qiáng)制轉(zhuǎn)換為特定類型。

if (emp is Person) {
  // Type check
  emp.firstName = 'Bob';
}
(emp as Person).firstName = 'Bob';

如果empnull或者不是Person對象, 那么第一個(gè)is的示例,后面將不回執(zhí)行; 第二個(gè)as的示例會(huì)拋出異常。
6.?.取值操作
使?.來代替.,可以避免因?yàn)樽筮厡ο罂赡転?code>null,導(dǎo)致的異常:

// 如果 p 為 non-null,設(shè)置它變量 y 的值為 4。
p?.y = 4;

運(yùn)算符重寫

有的語言里叫運(yùn)算符重載,都是為原來不支持這種操作的數(shù)據(jù)類型賦予這種運(yùn)算的能力,方便使用。這玩意兒OC也沒有,古老特點(diǎn)之三。
重載時(shí)需要用到operator這個(gè)關(guān)鍵字,后面跟上要重載的運(yùn)算符,下面就舉個(gè)簡單的+-重載的例子,其他的用法還蠻多,==的重載還要涉及到hashisEqual吧,這個(gè)應(yīng)該所有語言都差不多,具體的可以去網(wǎng)上專門搜一下,貼個(gè)
傳送門,這具體用到的時(shí)候再細(xì)看吧。

class Vector {
  final int x, y;

  Vector(this.x, this.y);

  Vector operator +(Vector v) => Vector(x + v.x, y + v.y);
  Vector operator -(Vector v) => Vector(x - v.x, y - v.y);
}

流程控制

1.for循環(huán)
除了基本的for-i和for-in循環(huán)之外,Dart對于實(shí)現(xiàn)了Iterable 接口的對象提供了forEach() 方法,如果不需要使用當(dāng)前計(jì)數(shù)值, 使用 forEach() 是非常棒的選擇。

candidates.forEach((candidate) => candidate.interview());

2.switch-case
每個(gè)case結(jié)尾需要加break,空case可以穿透,在非空case中實(shí)現(xiàn)fall-through形式,可以使用continue語句結(jié)合lable的方式實(shí)現(xiàn):

var command = 'CLOSED';
switch (command) {
  case 'CLOSED':
    executeClosed();
    continue nowClosed;
  // Continues executing at the nowClosed label.

  nowClosed:
  case 'NOW_CLOSED':
    // Runs for both CLOSED and NOW_CLOSED.
    executeNowClosed();
    break;
}

參考資料:
coderwhy-Flutter之搞定Dart系列
Dart編程語言中文網(wǎng)

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容