Dart簡明教程


【前言】Dart語言是使用flutter框架開發時候必備的語言,flutter是一個跨平台的框架,一套代碼就可以完美實現安卓和ios兩個平台,適配也很不錯,Dart語言很友好,和java很類似,學習成本也是很低的。所以這也是我推薦學習Dart語言的一個原因。

從本篇文章開始講解Dart語言的基本使用,我將會連續推出好幾篇文章詳解,希望幫助大家快速掌握Dart語言。


Dart的使用:

Dart中所有東西都是對象,包括數字、函數等。


目錄:

一、關鍵字(56個)
二、變量和常量
三、特殊數據類型
四、運算符 operators
五、控制流程語句 Control flow statements
六、函數 Function
七、異常 Exceptions
八、類 Classes
九、泛型 Generics
十、庫和可見性 Libraries and visibility
十一、異步支持 Asynchrony support
十二、生成器 Generators
十三、可調用的(Callable)類
十四、隔離 Isolates
十五、類型定義 Typedefs
十六、元數據 Metadata
十七、注釋 Comments
十八、概要 Summary


一、關鍵字(56個)

33個保留字(不能使用保留字作為標識符)

關鍵字 - - -
if superdo switch assert
else in this enum
is throw true break
new try case extends
null typedef catch var
class false void const
final rethrow while continue
finally return with for
default      

其中內置標志符有:(17個)

關鍵字 - - -
abstract deferred as dynamic
covariant export external factory
get implements import library
operator part set static
typedef      

其中Dart2相對於Dart1新增的,支持異步功能的關鍵字有:(6個)

關鍵字 - - -
async async* await sync*
yield yield*    

跟java相比,Dart特有的關鍵字有:(25個)

關鍵字 - - -
deferred as assert dynamic
sync* async async* in
is await export library
external typedef factory operator
var part const rethrow
covariant set yield get
yield*      

二、變量和常量

(一)變量的聲明,可以使用 var、Object 或 dynamic 關鍵字。

創建變量並初始化變量實例:

    var name = '張三' ;

變量存儲引用。

  •  

    1. 使用Object或dynamic關鍵字

    dynamic name = '張三';

調用的變量name包含對String值為“張三” 的對象的引用。
name推斷變量的類型是String,但可以通過指定它來更改該類型。
如果對象不限於單一類型(沒有明確的類型),請使用Object或dynamic關鍵字

    Object name = '張三';
    dynamic name = '李四';
  •  

    1. 顯式聲明將被推斷的類型

比如String,int等。

    //可以使用String顯示聲明字符串類型
    String name = '張三' ; //代替var name = '張三';

這個類型有很多,具體在下文有介紹。

(二)默認值

未初始化的變量的初始值為null(包括數字),因此數字、字符串都可以調用各種方法。

    //測試 數字類型的初始值是什么?
    int intDefaultValue;    // assert 是語言內置的斷言函數,僅在檢查模式下有效
    // 在開發過程中, 除非條件為真,否則會引發異常。(斷言失敗則程序立刻終止)
    assert(intDefaultValue == null);
    print(intDefaultValue);//打印結果為null,證明數字類型初始化值是null

(三)Final and const

如果您從未打算更改一個變量,那么使用 final 或 const,不是var,也不是一個類型。
一個 final 變量只能被設置一次;const 變量是一個編譯時常量。(Const變量是隱式的final。)
final的頂級或類變量在第一次使用時被初始化。

  • 1、被final或者const修飾的變量,變量類型可以省略。

//可以省略String這個類型聲明final name1 = "張三";//final String name1  = "張三";
    const name2 = "李四";//const String name2 = "李四";
  • 2、被 final 或 const 修飾的變量無法再去修改其值。

  final name1 = "張三";    // 這樣寫,編譯器提示:a final variable, can only be set once
    // 一個final變量,只能被設置一次。
    //name1 = "zhangsan";
    
    const name2 = "李四";    // 這樣寫,編譯器提示:Constant variables can't be assigned a value
    // const常量不能賦值
    // name2 = "lisi";
  • 3、注意:flnal 或者 const 不能和 var 同時使用,

    //這樣寫都會報錯
    //final var name1 = "張三";
    //const var name2 = "李四";
  • 4、常量如果是類級別的,請使用 static const

    static const speed = 100;
  • 5、常量的運算

    const speed = 100; //速度(km/h)
    const double distance = 2.5 * speed; // 距離 = 速度 * 時間

    final speed2 = 100; //速度(km/h)
    final double distance2 = 2.5 * speed2; // 距離 = 速度 * 時間
  • 6、const關鍵字不只是聲明常數變量。您也可以使用它來創建常量值,以及聲明創建常量值的構造函數。 任何變量都可以有一個常量值。

  // 注意: [] 創建的是一個空的list集合
  // const []創建一個空的、不可變的列表(EIL)。
  var varList = const []; // varList 當前是一個EIL
  final finalList = const []; // finalList一直是EIL
  const constList = const []; // constList 是一個編譯時常量的EIL

  // 可以更改非final,非const變量的值
  // 即使它曾經具有const值
  varList = ["haha"];  // 不能更改final變量或const變量的值
  // 這樣寫,編譯器提示:a final variable, can only be set once
  // finalList = ["haha"];
  // 這樣寫,編譯器提示:Constant variables can't be assigned a value  
  // constList = ["haha"];
  • 7、只要任何插值表達式是一個計算結果為null或數字,字符串或布爾值的編譯時常量,那么文字字符串就是編譯時常量。(關於$表達式和不同的數據類型后面會講解。)

// 這些是常量字符串const aConstNum = 0;const aConstBool = true;const aConstString = 'a constant string';// 這些不是常量字符串var aNum = 0;var aBool = true;var aString = 'a string';const aConstList = const [1, 2, 3];const validConstString = '$aConstNum $aConstBool $aConstString';//這樣用就會報錯:Const variables must be initialized with a constant value// const常量必須用conat類型的值初始化。// const invalidConstString = '$aNum $aBool $aString $aConstList';

三、特殊數據類型

Dart中支持以下特殊類型:

  • numbers 數字

  • strings 字符串

  • booleans 布爾

  • lists (also known as arrays) list集合(也稱為數組)

  • maps map集合

  • runes (for expressing Unicode characters in a string) 字符(用於在字符串中表示Unicode字符)

  • symbols 符號

(一)num 數字類型

num是數字類型的父類,有兩個子類 int 和 double。
num類型包括基本的運算符,如+,-,/和*,位運算符,如>>,在int類中定義。
如果num和它的子類沒有你要找的東西,math庫可能會找到。比如你會發現abs(),ceil()和floor()等方法。

(1) int

int表示整數,int的取值不大於64位,具體取決於平台。在Dart VM上,值可以從 -2的63次方 到 2的63次方減1.

整數是沒有小數點的數字。示例如下:

    int intNum1 = 10 ;    print(intNum1);
    int intNum2 = 0xDEADBEEF ;    print(intNum2);

(2) double

64位(雙精度)浮點數,如IEEE 754標准所規定。

如果一個數字包含一個小數,那么它就是一個double類型。示例如下:

    double doubleNum1 = 1.1;    print(doubleNum1);
    double doubleNum2 = 1.42e5;    print(doubleNum2);

(二)String 字符串

Dart里面的String是一系列 UTF-16代碼單元。

  • 1、您可以使用單引號或雙引號來創建一個字符串。

    String str1 = '單引號基本使用demo.';    String str2 = "雙引號基本使用demo.";
  • 2、單引號或者雙引號里面嵌套使用引號。

    //單引號里面嵌套單引號,必須在前面加反斜杠
    String str3 = '雙引號里面有單引號it\'s,必須在前面加反斜杠.';    //雙引號里面嵌套單引號(正常使用)
    String str4 = "雙引號里面有單引號it's.";    //單引號里面嵌套雙引號(正常使用)
    String str5 = '單引號里面有雙引號,編程開發初學必備語句"hello world"';    //雙引號里面嵌套雙引號,必須在前面加反斜杠
    String str6 = "雙引號里面有雙引號,編程開發初學必備語句\"hello world\"";
  • 3、多個字符串相鄰中間的空格問題:

經測試發現,除了單引號嵌套單引號或者雙引號嵌套雙引號不允許出現空串之外,其余的幾種情況都是可以運行的。
示例如下:

    // 這個會報錯
    //String blankStr1 = 'hello''''world';
    // 這兩個運行正常
    String blankStr2 = 'hello'' ''world'; //結果: hello world
    String blankStr3 = 'hello''_''world'; //結果: hello_world

    // 這個會報錯
    //String blankStr4 = "hello""""world";
    // 這兩個運行正常
    String blankStr5 = "hello"" ""world"; //結果: hello world
    String blankStr6 = "hello""_""world"; //結果: hello_world

    //單引號里面有雙引號,混合使用運行正常
    String blankStr7 = 'hello""""world'; //結果: hello""""world
    String blankStr8 = 'hello"" ""world'; //結果: hello"" ""world
    String blankStr9 = 'hello""_""world'; //結果: hello""_""world

    //雙引號里面有單引號,混合使用運行正常
    String blankStr10 = "hello''''world"; //結果: hello''''world
    String blankStr11 = "hello'' ''world"; //結果: hello'' ''world
    String blankStr12 = "hello''_''world"; //結果: hello''_''world
  • 4、您可以使用相鄰字符串文字或+ 運算符連接字符串:

例如:

    > 直接把相鄰字符串寫在一起,就可以連接字符串了。

    String connectionStr1 =  '字符串連接'
    '甚至可以在'
    '換行的時候進行。';

    > 用+把相鄰字符串連接起來。

    String connectionStr2 =  '字符串連接'
      + '甚至可以在'
      + '換行的時候進行。';

    > 使用單引號或雙引號的三引號:
    
    String connectionStr3 = ''' 
      你可以創建
      像這樣的多行字符串。
      ''' ;

    String connectionStr4 = """這也是一個
      多行字符串。""";
  • 5、關於轉義符號的使用

聲明raw字符串(前綴為r),在字符串前加字符“r”,或者在\前面再加一個\,
可以避免“\”的轉義作用,在正則表達式里特別有用

舉例如下:

    print(r"換行符:\n"); //這個結果是 換行符:\n
    print("換行符:\\n"); //這個結果是 換行符:\n
    print("換行符:\n");  //這個結果是 換行符:
  • 6、可以使用${表達式}將表達式的值放入字符串中。如果表達式是標識符,則可以跳過{}。
    為了獲得對應於object的字符串,Dart調用object的toString()方法。

例如:

    String replaceStr1 = '字符串連接';    print('$replaceStr1'
        + '甚至可以在換行的時候進行。' == '字符串連接'
        + '甚至可以在換行的時候進行。');

    String replaceStr2 = 'Android Studio';    print('你知道' +        '${replaceStr2.toUpperCase()}'
          + '最新版本是多少嗎?' ==          '你知道ANDROID STUDIO最新版本是多少嗎?');

注:
==操作符測試兩個對象是否相等。如果兩個字符串包含相同的代碼單元序列,那么它們是等效的。

有關如何在字符串中表示Unicode字符的詳細信息,請參見下文“字符”)。
關於String的更多詳細的api用法,后文會專門講解。

(三)bool 布爾值

為了表示布爾值,Dart有一個名為的類型bool。
只有兩個對象具有bool類型:true和false,它們都是編譯時常量。

Dart的類型安全意味着您不能使用if(nonbooleanValue)或assert(nonbooleanValue)等代碼。
相反,Dart使用的是顯式的檢查值,如下所示:

    // 檢查是否為空字符串
    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);

assert 是語言內置的斷言函數,僅在檢查模式下有效
在開發過程中, 除非條件為真,否則會引發異常。(斷言失敗則程序立刻終止)。

(四)list 集合(也稱為數組)

幾乎所有編程語言中最常見的集合可能是數組或有序對象組。
在Dart中,數組是List對象,因此大多數人只是將它們稱為List。
Dart list文字看起來像JavaScript數組文字。 以下是一個簡單的Dart列表:

    //創建一個int類型的list
    List list = [10, 7, 23];    print(list);

要創建一個編譯時常量const的list,示例如下:

    List constantList = const[10,3,15];    print(constantList);

注意事項:

1.可以直接打印list包括list的元素,list也是一個對象。但是java必須遍歷才能打印list,直接打印是地址值。2.和java一樣list里面的元素必須保持類型一致,不一致就會報錯。3.和java一樣list的角標從0開始。

關於list的相關api介紹,后面會做詳細講解。

(五)map集合

一般來說,map是將鍵和值相關聯的對象。鍵和值都可以是任何類型的對象。
每個鍵只出現一次,但您可以多次使用相同的值。Dart支持map由map文字和map類型提供。

  • 1、兩種創建方式:

直接聲明,用{}表示,里面寫key和value,每組鍵值對中間用逗號隔開

    Map companys = {'first': '阿里巴巴', 'second': '騰訊', 'fifth': '百度'};
    print(companys);//打印結果 {first: 阿里巴巴, second: 騰訊, fifth: 百度}

先聲明,再去賦值。(以變幾種形式都是可以的。)

    Map companys1 = new Map();
    companys1['first'] = '阿里巴巴';
    companys1['second'] = '騰訊';
    companys1['fifth'] = '百度';
    print(companys1);    //打印結果 {first: 阿里巴巴, second: 騰訊, fifth: 百度}

    var companys2 = new Map();
    companys2['first'] = '阿里巴巴';
    companys2['second'] = '騰訊';
    companys2['fifth'] = '百度';
    print(companys2);    //換成var 打印結果是一樣的 {first: 阿里巴巴, second: 騰訊, fifth: 百度}

    Map companys3 = new Map();
    companys3["first"] = "阿里巴巴";
    companys3["second"] = "騰訊";
    companys3["fifth"] = "百度";
    print(companys3);    //換成雙引號 打印結果 {first: 阿里巴巴, second: 騰訊, fifth: 百度}

    var companys4 = new Map();
    companys4["first"] = "阿里巴巴";
    companys4["second"] = "騰訊";
    companys4["fifth"] = "百度";
    print(companys4);    //換成雙引號,換成var 打印結果 {first: 阿里巴巴, second: 騰訊, fifth: 百度}
  • 2、添加元素。格式 變量名[key] = value;

注意:key可以是不同類型。

  //添加一個新的元素,key為 4  value為 華為
  companys[4] = '華為';  print(companys);//打印結果 {first: 阿里巴巴, second: 騰訊, fifth: 百度, 4: 華為}
  • 3、修改元素

  //把key為first的元素對應的value改成 alibaba
  companys['first'] = 'alibaba';  print(companys);//打印結果 {first: alibaba, second: 騰訊, fifth: 百度, 4: 華為}
  • 4、注意事項

  // map里面的value可以相同
  Map company1 = {    'first': '阿里巴巴', 'second': '騰訊', 5: '百度','new key': '阿里巴巴'};
  print(company1);  //打印結果 {first: 阿里巴巴, second: 騰訊, 5: 百度, new key: 阿里巴巴}

  Map company2 = new Map();
  company2['first'] = '阿里巴巴';
  company2['second'] = '騰訊';
  company2['fifth'] = '百度';
  company2['new key'] = '阿里巴巴';  // map里面的value可以相同
  company2['new key2'] = '';  // map里面value可以為空字符串
  company2['new key3'] = null;  // map里面的value可以為null
  print(company2);  //打印結果 {first: 阿里巴巴, second: 騰訊, fifth: 百度, new key: 阿里巴巴, new key2: , new key3: null}
  • 5、要創建一個編譯時常量const的map,請在map文字之前添加const:

    final fruitConstantMap = const {2: 'apple',10: 'orange',18: 'banana'};
  • 6、小結:

    1.創建map有兩種方式。    2.map的key類型不一致也不會報錯。    3.添加元素的時候,會按照你添加元素的順序逐個加入到map里面,哪怕你的key,
    比如分別是 1,2,4,看起來有間隔,事實上添加到map的時候是{1:value,2:value,4:value} 這種形式。    4.添加的元素的key如果是map里面某個key的英文,照樣可以添加到map里面。    5.map里面的key不能相同。但是value可以相同,value可以為空字符串或者為null。

關於map的相關api介紹,后面會做詳細講解。

(六)runes (for expressing Unicode characters in a string) 字符(用於在字符串中表示Unicode字符)

Unicode為世界上所有的書寫系統中使用的每個字母,數字和符號定義了唯一的數值。

由於Dart字符串是UTF -16代碼單元的序列,所以在字符串中表達32位Unicode值需要特殊的語法。
表示Unicode代碼點的常用方法是\uXXXX,其中XXXX是一個4位十六進制值。

例如,心形字符()是\u2665。
要指定多於或少於4個十六進制數字,請將該值放在大括號中。 例如,笑的表情符號()是\u{1f600}。

String類有幾個屬性可以用來提取符文信息。 codeUnitAt和codeUnit屬性返回16位代碼單元。
使用Runes屬性來獲得一個string的符文。

以下示例說明了符文,16位代碼單元和32位代碼點之間的關系。

    var clapping = '\u{1f44f}';    print(clapping);    print(clapping.codeUnits);    print(clapping.runes.toList());    //這里使用String.fromCharCodes方法顯示字符圖形
    //String的詳細api后面會具體講解。
    Runes input = new Runes(        '\u2665  \u{1f605}  \u{1f60e}  \u{1f47b}  \u{1f596}  \u{1f44d}');    print(new String.fromCharCodes(input));

(七)symbols 符號

有兩個 #radix   #bar  可以使用
官網文檔沒看明白這個具體是做什么的。。暫且放着。
這個用的很少,基本用不到的。


四、運算符 operators

描述 操作符  
一元后綴 expr++    expr--    ()    []    .    ?.  
一元前綴 -expr    !expr    ~expr    ++expr    --expr  
* / % ~/  
添加劑 + -  
轉移 << >>  
按位異或 ^  
按位與 &  
按位或 |  
邏輯與 &&  
邏輯或 ||  
關系型和類型測試 >=    >    <=    <    as    is    is!  
平等 ==    !=  
如果為空 ??  
有條件的 expr1 ? expr2 : expr3  
級聯 ..  
分配 =    *=    /=    ~/=    %=    +=    -=    <<=    >>=    &=    ^=    ` =??=`

(一)算術運算符:

操作符 含義
+
減去
-expr 一元減號,也稱為否定(反轉表達的符號),比如-1,表示數字負一
*
/
~/ 除法,返回一個整數結果
% 獲取整數除法的余數(模)
var++ 先引用后增加
++var 先增加后引用
var-- 先引用后減少
--var 先減少后引用

(二)賦值運算符:

操作符 含義
=  
+=  
–=  
*=  
/=  
~/=  
%=  
&=  
|=  
^=  
>>=  
<<=  

(三)關系運算符:

操作符 含義
== 等於
!= 不等於
> 大於
< 小於
>= 大於或等於
<= 小於或等於

(四)邏輯運算符:

操作符 含義
!expr 反轉表達式(將false更改為true,反之亦然)
|| 邏輯雙或
&& 邏輯雙與

注意了:沒有邏輯或|,沒有邏輯與&

(五)位運算符:

操作符 含義 解釋
& 位與 有0則0
| 位或 有1則1
^ 位異或 相同為0,不同為1
~expr 按位取反(包括符號位)  

(六)位移運算符:

操作符 含義 用法解釋
<< 向左移動 左邊最高位丟棄,左邊補齊0
>> 向右移動 最高位是0,左邊補齊0;最高位是1,左邊補齊1
>>> 無符號右移 不管首位是0還是1,都在左邊補0

(七)三元運算符:

Dart有兩個運算符,可以讓您精確地評估可能需要if-else語句的表達式:

condition ? expr1 : expr2

如果條件為真,則返回expr1的值; 否則返回expr2的值。

expr1 ?? expr2

如果expr1非空,則返回其值; 否則,評估並返回expr2的值。

(八)其他符號:

操作符 作用范圍 含義
() 函數應用程序 代表一個函數調用
[] List訪問 引用List中指定索引處的值
. 成員訪問 指表達的財產; 例如:foo.bar從表達式foo中選擇屬性欄
?. 條件成員訪問 .一樣,但最左邊的操作數可以為空; 例如:foo?.bar從表達式foo中選擇屬性bar,除非foo為空(當foo為空時,foo?.bar的值為空)
.. 級聯符號 級聯符號..允許您在同一個對象上進行一系列操作。 除了函數調用之外,還可以訪問同一對象上的字段。其實相當於java的鏈式調用。(這個在后面講函數的時候會具體講解。)

(九)類型測試操作符:

as, is, is!操作符可以方便地在運行時檢查類型。

操作符 意義
as 判斷屬於某種類型
is 如果對象具有指定的類型,則為true
is! 如果對象具有指定的類型,則為false

五、函數 Function

Dart是一種真正的面向對象的語言,所以即使是函數也是對象,並且有一個類型Function。這意味着函數可以分配給變量或作為參數傳遞給其他函數。你也可以調用一個Dart類的實例,就像它是一個函數一樣。有關詳細信息,請參閱Callable類。

以下是一個實現函數的例子:

bool isNoble(int atomicNumber) {  return _nobleGases[atomicNumber] != null;
}

雖然Effective Dart建議使用 公共API的類型注釋,但如果您省略這些類型,該函數仍然有效:

isNoble(atomicNumber) {  return _nobleGases[atomicNumber] != null;
}

對於只包含一個表達式的函數,可以使用簡寫語法:

bool isNoble (int atomicNumber )=> _nobleGases [ atomicNumber ] != null ;

該語法是一個速記 。該表示法有時也稱為脂肪箭頭語法。=> expr{ return expr; }=>

注意:箭頭(=>)和分號(;)之間 只能出現一個表達式 - 不包括語句。例如,你不能在那里放一個if語句,但你可以使用一個條件表達式。

函數可以有兩種類型的參數:必需的和可選的。首先列出所需參數,然后列出任何可選參數。

(一)main()函數

每個應用程序都必須有一個頂層main()函數,它可以作為應用程序的入口點。該main()函數返回void並具有List<String>參數的可選參數。

例如:

void main() {
  querySelector('#sample_text_id')
    ..text = 'Click me!'
    ..onClick.listen(reverseText);
}

【注意:】上述代碼中的..語法稱為級聯。通過級聯,可以對單個對象的成員執行多個操作。

級聯符號..允許您在同一個對象上進行一系列操作。除了函數調用之外,還可以訪問同一對象上的字段。這通常會為您節省創建臨時變量的步驟,並允許您編寫更流暢的代碼。

請看下面的代碼:

querySelector('#confirm') // Get an object.
  ..text = 'Confirm' // Use its members.
  ..classes.add('important')
  ..onClick.listen((e) => window.alert('Confirmed!'));

第一個方法調用querySelector()返回一個選擇器對象。遵循級聯表示法的代碼對該選擇器對象進行操作,忽略可能返回的任何后續值。

上述例子相當於:

var button = querySelector('#confirm');
button.text = 'Confirm';
button.classes.add('important');
button.onClick.listen((e) => window.alert('Confirmed!'));

級聯符號也可以嵌套使用。 例如:

final addressBook = (AddressBookBuilder()
      ..name = 'jenny'
      ..email = 'jenny@example.com'
      ..phone = (PhoneNumberBuilder()
            ..number = '415-555-0100'
            ..label = 'home')
          .build())
    .build();

當返回值是void時不能構建級聯。 例如,以下代碼失敗:

var sb = StringBuffer();
sb.write('foo')
  ..write('bar'); // 這里會報錯

上例中的sb.write()調用返回的是void,當返回值是void時不能構建級聯。

【注意:】 嚴格地說,級聯的..符號不是操作符。它只是Dart語法的一部分。

(二)可選參數

可選的命名參數

定義函數時,使用{param1, param2, …},用於指定命名參數。例如:

//設置[bold]和[hidden]標志void enableFlags({bool bold, bool hidden}) {    // ... }

調用函數時,可以使用指定命名參數。例如:paramName: value

enableFlags(bold: true, hidden: false);

可選的位置參數

包裝一組函數參數,用[]它們標記為可選的位置參數:

String say(String from, String msg, [String device]) {  var result = '$from says $msg';  if (device != null) {
    result = '$result with a $device';
  }  return result;
}

下面是一個不帶可選參數調用這個函數的例子:

say('Bob', 'Howdy'); //結果是: Bob says Howdy

下面是用第三個參數調用這個函數的例子:

say('Bob', 'Howdy', 'smoke signal'); //結果是:Bob says Howdy with a smoke signal

默認參數的值

函數可以使用=為命名參數和位置參數定義默認值。默認值必須是編譯時常量。如果沒有提供默認值,則默認值為null

下面是為命名參數設置默認值的示例:

/// 設置 bold 和 hidden 標記的默認值都為falsevoid enableFlags2({bool bold = false, bool hidden = false}) {  // ...}// 調用的時候:bold will be true; hidden will be false.enableFlags2(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;
}//調用方式:say('Bob', 'Howdy'); //結果為:Bob says Howdy with a carrier pigeon;

您還可以將list或map作為默認值傳遞。下面的示例定義一個函數doStuff(),該函數指定列表參數的默認listgifts參數的默認map。

/// 使用list 或者map設置默認值void doStuff(
    {List<int> list = const [1, 2, 3],    Map<String, String> gifts = const {      'first': 'paper',      'second': 'cotton',      'third': 'leather'
    }}) {
  print('list:  $list');
  print('gifts: $gifts');
}

(三)作為一個類對象的功能

您可以將一個函數作為參數傳遞給另一個函數。

例1:

void printElement(int element) {
  print(element);
}

var list = [1, 2, 3];// 把 printElement函數作為一個參數傳遞進來list.forEach(printElement);

您也可以將一個函數分配給一個變量。

例2:

var loudify = (msg) => '!!! ${msg.toUpperCase()} !!!';
assert(loudify('hello') == '!!! HELLO !!!');

上面例2使用了一個匿名函數。更多關於下一節中的內容:

(四)匿名函數

大多數函數都能被命名為匿名函數,如main()printElement()
您還可以創建一個名為匿名函數的無名函數,有時也可以創建lambda或閉包。
您可以為變量分配一個匿名函數,例如,您可以從集合中添加或刪除它。

一個匿名函數看起來類似於一個命名函數 - 0或更多的參數,在括號之間用逗號和可選類型標注分隔。

下面的代碼塊包含函數的主體:

例1:

([[Type] param1[, …]]) { 
  codeBlock; 
};

下面的示例定義了一個具有無類型參數的匿名函數item
該函數被list中的每個item調用,輸出一個字符串,該字符串包含指定索引處的值。

例2:

var list = ['apples', 'bananas', 'oranges'];list.forEach((item) {  print('${list.indexOf(item)}: $item');
});

如果函數只包含一條語句,可以使用箭頭符號=>來縮短它。

比如上面的例2可以簡寫成:

例3:

list.forEach(
    (item) => print('${list.indexOf(item)}: $item'));

(五)語法作用域

Dart是一種具有語法范圍的語言,這意味着變量的范圍是靜態確定的,只需通過代碼布局來確定。
您可以跟隨花括號向外以查看變量是否在范圍內。

這里有一個嵌套函數的例子,每個作用域級別上都有變量:

bool topLevel = true;void main() {
  var insideMain = true;  void myFunction() {
    var insideFunction = true;    void nestedFunction() {
      var insideNestedFunction = true;      assert(topLevel);      assert(insideMain);      assert(insideFunction);      assert(insideNestedFunction);
    }
  }
}

請注意nestedFunction()方法中,從每個級別的變量直到頂級,是如何使用的。

(六)語法閉包

閉包是一個函數對象,它可以訪問其語法范圍內的變量,即使函數在其原始范圍之外使用。

函數可以關閉周圍作用域中定義的變量。

在下面的示例中,makeAdder()捕獲變量addBy。無論返回的函數到哪里,它都會記住addBy。

///向函數參數添加[addBy],並返回該函數。Function makeAdder(num addBy) {  return (num i) => addBy + i;
}void main() {  var add2 = makeAdder(2);  var add4 = makeAdder(4);

  assert(add2(3) == 5);
  assert(add4(3) == 7);
}

(七)測試等式函數

下面是一個測試頂級函數、靜態方法和相等實例方法的示例:

void foo() {} // 一個頂級函數class A {  static void bar() {} //一個靜態方法
  void baz() {} //實例方法}void main() {
  var x;  // 比較頂級的函數
  x = foo;  assert(foo == x);  // 比較靜態方法
  x = A.bar;  assert(A.bar == x);  // 比較實例方法
  var v = A(); // A類的實例1
  var w = A(); // A類的實例2
  var y = w;
  x = w.baz;  //這些閉包指向同一個實例(#2),所以它們相等。
  assert(y.baz == x);  //這些閉包是指不同的實例,所以他們不平等。
  assert(v.baz != w.baz);
}

(八)返回值

所有函數都返回一個值。如果沒有指定返回值,則語句return null;隱式地附加到函數體。

foo() {}assert(foo() == null);

六、控制流程語句 Control flow statements

七、異常 Exceptions

八、類 Classes

九、泛型 Generics

十、庫和可見性 Libraries and visibility

十一、異步支持 Asynchrony support

十二、生成器 Generators

十三、可調用的(Callable)類

十四、隔離 Isolates

十五、類型定義 Typedefs

十六、元數據 Metadata

十七、注釋 Comments

十八、概要 Summary


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM