Dart簡明教程

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

從本篇文章開始講解Dart語言的基本使用,我將會連續推出好幾篇文章詳解,但願幫助你們快速掌握Dart語言。ios


Dart的使用:正則表達式

Dart中全部東西都是對象,包括數字、函數等。express


目錄:編程

1、關鍵字(56個)
2、變量和常量
3、特殊數據類型
4、運算符 operators
5、控制流程語句 Control flow statements
6、函數 Function
7、異常 Exceptions
8、類 Classes
9、泛型 Generics
10、庫和可見性 Libraries and visibility
11、異步支持 Asynchrony support
12、生成器 Generators
十3、可調用的(Callable)類
十4、隔離 Isolates
十5、類型定義 Typedefs
十6、元數據 Metadata
十7、註釋 Comments
十8、概要 Summaryapi


1、關鍵字(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*      

2、變量和常量

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

建立變量並初始化變量實例:數組

    var name = '張三' ;

變量存儲引用。安全

  •  

    1. 使用Object或dynamic關鍵字閉包

    dynamic name = '張三';

調用的變量name包含對String值爲「張三」 的對象的引用。
name推斷變量的類型是String,但能夠經過指定它來更改該類型。
若是對象不限於單一類型(沒有明確的類型),請使用Object或dynamic關鍵字app

    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的頂級或類變量在第一次使用時被初始化。

  • 一、被final或者const修飾的變量,變量類型能夠省略。

//能夠省略String這個類型聲明final name1 = "張三";//final String name1  = "張三";
    const name2 = "李四";//const String name2 = "李四";
  • 二、被 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";
  • 三、注意:flnal 或者 const 不能和 var 同時使用,

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

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

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

    final speed2 = 100; //速度(km/h)
    final double distance2 = 2.5 * speed2; // 距離 = 速度 * 時間
  • 六、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"];
  • 七、只要任何插值表達式是一個計算結果爲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';

3、特殊數據類型

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代碼單元。

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

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

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

經測試發現,除了單引號嵌套單引號或者雙引號嵌套雙引號不容許出現空串以外,其他的幾種狀況都是能夠運行的。
示例以下:

    // 這個會報錯
    //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
  • 四、您可使用相鄰字符串文字或+ 運算符鏈接字符串:

例如:

    > 直接把相鄰字符串寫在一塊兒,就能夠鏈接字符串了。

    String connectionStr1 =  '字符串鏈接'
    '甚至能夠在'
    '換行的時候進行。';

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

    String connectionStr2 =  '字符串鏈接'
      + '甚至能夠在'
      + '換行的時候進行。';

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

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

聲明raw字符串(前綴爲r),在字符串前加字符「r」,或者在\前面再加一個\,
能夠避免「\」的轉義做用,在正則表達式裏特別有用

舉例以下:

    print(r"換行符:\n"); //這個結果是 換行符:\n
    print("換行符:\\n"); //這個結果是 換行符:\n
    print("換行符:\n");  //這個結果是 換行符:
  • 六、可使用${表達式}將表達式的值放入字符串中。若是表達式是標識符,則能夠跳過{}。
    爲了得到對應於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類型提供。

  • 一、兩種建立方式:

直接聲明,用{}表示,裏面寫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: 百度}
  • 二、添加元素。格式 變量名[key] = value;

注意:key能夠是不一樣類型。

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

  //把key爲first的元素對應的value改爲 alibaba
  companys['first'] = 'alibaba';  print(companys);//打印結果 {first: alibaba, second: 騰訊, fifth: 百度, 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}
  • 五、要建立一個編譯時常量const的map,請在map文字以前添加const:

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

    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  可使用
官網文檔沒看明白這個具體是作什麼的。。暫且放着。
這個用的不多,基本用不到的。


4、運算符 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

5、函數 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);

6、控制流程語句 Control flow statements

7、異常 Exceptions

8、類 Classes

9、泛型 Generics

10、庫和可見性 Libraries and visibility

11、異步支持 Asynchrony support

12、生成器 Generators

十3、可調用的(Callable)類

十4、隔離 Isolates

十5、類型定義 Typedefs

十6、元數據 Metadata

十7、註釋 Comments

十8、概要 Summary

相關文章
相關標籤/搜索