- 用Flutter極速構(gòu)建原生應(yīng)用
- 張益琿
- 3123字
- 2020-01-20 15:01:05
3.1 使用函數(shù)
函數(shù)是編程中最偉大的發(fā)明。有了函數(shù),我們可以將復(fù)雜的問題簡單化,將龐大的程序分解開。函數(shù)使得代碼復(fù)用真正實(shí)現(xiàn),并且在其基礎(chǔ)上產(chǎn)生了更加面向應(yīng)用的編程方式。本節(jié)我們就來學(xué)習(xí)Dart中函數(shù)的應(yīng)用。
3.1.1 關(guān)于main函數(shù)
任何Dart應(yīng)用程序都需要有一個main函數(shù)作為整個應(yīng)用程序的入口。我們之前編寫的所有程序都有一個main函數(shù),main函數(shù)不一定要在程序的開頭,但是它一定會作為程序的入口,在main函數(shù)中,我們可以編寫邏輯代碼,也可以調(diào)用其他函數(shù)。
在數(shù)學(xué)中,函數(shù)代表了一種運(yùn)算規(guī)則,函數(shù)有定義域、值域和映射關(guān)系3要素。在編程中,函數(shù)的概念與數(shù)學(xué)中函數(shù)的概念相差不多,也有3要素,分別為參數(shù)、返回值和函數(shù)體。任何一個函數(shù)都由這3部分組成,在平時編寫main函數(shù)時,我們隱藏了返回值并且忽略了參數(shù),一個完整的main函數(shù)編寫如下:

可以發(fā)現(xiàn),main函數(shù)其實(shí)是一個返回值是void并且有一個字符串列表參數(shù)的函數(shù)。我們之前運(yùn)行Dart代碼時,從沒有向main函數(shù)中傳遞過參數(shù),其實(shí)可以傳遞任意個字符串參數(shù)進(jìn)去,可以在終端使用Dart工具來執(zhí)行上面的main函數(shù),并且進(jìn)行參數(shù)的傳遞,代碼如下:
dart func1.dart 琿少 hello
執(zhí)行指令后,終端會輸出接收到的參數(shù)列表:[琿少, hello]。
3.1.2 自定義函數(shù)
Dart系統(tǒng)庫為我們編寫了許多常用的函數(shù)。例如,在學(xué)習(xí)數(shù)據(jù)類型的時候,每一種數(shù)據(jù)類型中都封裝有對應(yīng)的函數(shù),通過這些函數(shù)我們可以方便地實(shí)現(xiàn)一些通用的功能。但是Dart并不是萬能的,它只能提供基礎(chǔ)的工具,要打造出精美的應(yīng)用,除了要使用這些基礎(chǔ)的工具外,必要的時候還需要借助別人創(chuàng)造的工具或者使用自己創(chuàng)造的工具。
函數(shù)就是Dart中基礎(chǔ)的工具,自定義函數(shù)也很簡單,只要把握住函數(shù)的3要素即可,格式如下:

可以編寫一個簡單的加法器函數(shù),代碼如下:

這是一個有兩個num類型的參數(shù)并且返回值為num類型的函數(shù),a和b為傳遞進(jìn)函數(shù)的參數(shù)名,在函數(shù)體內(nèi)可以通過參數(shù)名來獲取參數(shù)的值進(jìn)行使用,通過函數(shù)體的運(yùn)算后,使用return語句將結(jié)果返回。在main函數(shù)中對自定義的函數(shù)體進(jìn)行調(diào)用,代碼如下:

通過函數(shù)名加小括號的方式可以對函數(shù)進(jìn)行調(diào)用,小括號中可以傳遞函數(shù)所需的所有參數(shù)。需要注意,在調(diào)用函數(shù)時,傳遞進(jìn)函數(shù)的參數(shù)個數(shù)與類型必須和函數(shù)定義的參數(shù)個數(shù)和類型完全一致,數(shù)量不符或類型不匹配都會產(chǎn)生錯誤。
其實(shí)Dart是一門真正的面向?qū)ο笳Z言,也就是說,不論是字符串、數(shù)值、布爾值還是函數(shù),在Dart中都一視同仁,它們都是對象。因此,它們都有對象的行為和特性,你可以將函數(shù)對象賦值給一個變量,或者將函數(shù)對象作為參數(shù)傳遞給另一個函數(shù),例如:

雖然我們說,函數(shù)3要素是函數(shù)的關(guān)鍵,但是Dart語言提供了極簡的編程方式和極暢快的編程體驗,因此無論是返回值的類型還是參數(shù)的類型,在定義函數(shù)時都可以省略。Dart會根據(jù)傳入?yún)?shù)和return語句返回的值來自動匹配類型,對于開發(fā)者來說,這是一個非常好用的特性,例如:

如果你覺得上面定義函數(shù)的形式還不夠簡潔,沒關(guān)系,Dart中還提供了箭頭函數(shù),若某個函數(shù)的函數(shù)體只有一句語句(就如上面的addFunc函數(shù)),則使用箭頭函數(shù)只需要一行代碼即可定義,示例如下:
num addFunc2(num a,num b)=>a+b;
也可以將參數(shù)類型和返回值類型省略,示例如下:
addFunc2(a,b)=>a+b;
箭頭函數(shù)的格式如下:
返回值 函數(shù)名(參數(shù))=>函數(shù)體語句
和普通函數(shù)一樣,返回值和參數(shù)的類型都可以省略,并且唯一的一個函數(shù)體語句執(zhí)行的結(jié)果會被當(dāng)作返回值返回。
3.1.3 定義可選參數(shù)的函數(shù)
對于前面我們所編寫的函數(shù),在調(diào)用時,其傳入的參數(shù)個數(shù)與類型必須與函數(shù)定義的一致。這種要求在實(shí)際開發(fā)中通常會稍顯嚴(yán)格,有的時候,我們編寫的函數(shù)的參數(shù)并非都是必須傳入的,Dart函數(shù)提供位置可選參數(shù)與名稱可選參數(shù)兩種方式來定義可選參數(shù)的函數(shù)。
可選參數(shù)是指在調(diào)用函數(shù)時,某個參數(shù)是可選的,即調(diào)用者可以選擇傳入此參數(shù),也可以選擇不傳入。在Dart中,可選參數(shù)分為名稱可選參數(shù)和位置可選參數(shù)。對于名稱可選參數(shù),函數(shù)的定義格式如下所示:
返回值類型 函數(shù)名({參數(shù)列表}){ 函數(shù)體 }
和前面我們所學(xué)習(xí)的函數(shù)唯一不同的地方在于參數(shù)列表被放入了大括號中。對于名稱可選函數(shù),其返回值類型和參數(shù)類型也可以省略。下面是一個名稱可選參數(shù)函數(shù)的示例:

muFunc函數(shù)中定義了兩個參數(shù),分別表示姓名和年齡,這兩個參數(shù)都是可選的,在調(diào)用的時候,我們需要使用參數(shù)名加冒號的方式來進(jìn)行參數(shù)的傳遞,參數(shù)的先后順序并不重要,并且調(diào)用者也可以選擇只傳一部分參數(shù)或者不傳參數(shù),函數(shù)在執(zhí)行時都不會產(chǎn)生錯誤。
位置可選參數(shù)函數(shù)是指函數(shù)某個位置的參數(shù)是可選的,即調(diào)用者可以選擇傳這個參數(shù),也可以選擇不傳這個參數(shù)。位置可選參數(shù)函數(shù)更加簡單,其只需要將可選的參數(shù)放入中括號中即可,例如:

myFunc2函數(shù)定義了兩個參數(shù),其中第一個參數(shù)是必選的,調(diào)用者必須傳這個參數(shù),表示年齡的age參數(shù)則是可選的,例如下面的代碼調(diào)用這個函數(shù)完全正確:
myFunc2("琿少");
有了可選參數(shù)函數(shù),我們編寫Dart程序時將有更大的靈活性,這只是Dart中函數(shù)功能強(qiáng)大的一方面,在3.1.4節(jié)中,我們將介紹可選參數(shù)的默認(rèn)值,可選參數(shù)配合默認(rèn)值一起使用,不僅使函數(shù)非常靈活,也使其安全性得到了保證。
3.1.4 函數(shù)可選參數(shù)的默認(rèn)值
可選參數(shù)的函數(shù)在調(diào)用時,如果調(diào)用者沒有傳入某個參數(shù),函數(shù)中獲取到的此參數(shù)值就為null,例如:

在定義可選參數(shù)函數(shù)時,我們也可以為這些可選的參數(shù)設(shè)置一個默認(rèn)值,設(shè)置默認(rèn)值后,如果調(diào)用者沒有傳入這個參數(shù),函數(shù)內(nèi)就會使用此參數(shù)的默認(rèn)值。名稱可選參數(shù)函數(shù)設(shè)置默認(rèn)值的方式如下:

位置可選參數(shù)函數(shù)設(shè)置默認(rèn)值的方式如下:

在定義可選參數(shù)函數(shù)時,我們應(yīng)盡量為其提供一個默認(rèn)值,默認(rèn)值可以使函數(shù)的執(zhí)行更加可控,程序的執(zhí)行更加安全。
3.1.5 匿名函數(shù)
我們知道,通過函數(shù)名可以進(jìn)行函數(shù)的調(diào)用,然而并非所有函數(shù)都有名字,在Dart中,沒有名字的函數(shù)被稱為匿名函數(shù)。匿名函數(shù)可以直接賦值給變量,通過變量來進(jìn)行函數(shù)的調(diào)用,也可以通過匿名函數(shù)來創(chuàng)建自執(zhí)行的函數(shù),例如:

上面的示例代碼中,func變量被賦值成一個函數(shù)對象,在main函數(shù)中使用func變量進(jìn)行了函數(shù)的調(diào)用,main函數(shù)中還定義了一個自執(zhí)行匿名函數(shù)。所謂自執(zhí)行函數(shù),是指函數(shù)的創(chuàng)建和執(zhí)行一步完成,其和正常的函數(shù)一樣,自執(zhí)行函數(shù)可以有參數(shù),也可以有返回值。其實(shí)對于自執(zhí)行函數(shù),除了可以將某些邏輯聚成一個代碼塊外,其更大的作用是會生成一個新的內(nèi)部作用域,內(nèi)部作用域可以防止外部變量對作用域內(nèi)變量的污染,也可以防止在同一個作用域中產(chǎn)生太多的變量。關(guān)于作用域的相關(guān)內(nèi)容在3.1.6小節(jié)介紹。
3.1.6 詞法作用域
所謂作用域,其實(shí)指的就是變量的有效范圍,在Dart中,大括號會生成作用域,也就是說,條件結(jié)構(gòu)、循環(huán)結(jié)構(gòu)、函數(shù)等都會生成作用域。在作用域內(nèi)聲明或定義的變量,出了作用域就被銷毀并且無法使用,例如:

但是,外層作用域中的變量是可以在內(nèi)層作用域中使用的,例如:

在Dart中,作用域是可以防止變量污染的,如果在內(nèi)層作用域中聲明了和外層作用域中名字一樣的變量,內(nèi)層作用域中就不能再使用外層作用域的變量,示例如下:

3.1.7 關(guān)于閉包
閉包也是函數(shù),它是函數(shù)在一種特殊場景下的應(yīng)用。3.1.6小節(jié)我們了解了詞法作用域的基本知識,正常情況下,變量離開其作用域就會失效,但閉包是一種特殊情況。
閉包是一個函數(shù)對象,其特點(diǎn)是當(dāng)變量離開其作用域后依然可以被函數(shù)內(nèi)部使用,例如:

上面的示例代碼中,func函數(shù)會返回一個匿名函數(shù),這個匿名函數(shù)就是閉包,在調(diào)用函數(shù)時,我們傳入了一個字符串參數(shù)name,僅從詞法作用域來看,name變量只能在函數(shù)func內(nèi)使用,出了作用域就會失效。在示例代碼中,特殊的是func函數(shù)返回了一個新的函數(shù),這個函數(shù)中對name變量進(jìn)行了引用,這時這個新的函數(shù)就變成了閉包,其會對使用到的變量進(jìn)行拷貝,即使func函數(shù)結(jié)束,離開了原name參數(shù)變量的作用域,閉包中引用的變量依然有效。
閉包是一種非常常用的語法結(jié)構(gòu),在實(shí)際開發(fā)中,我們也經(jīng)常會使用到它。雖然閉包的概念略微有些難以理解,但是應(yīng)用十分簡單,我們可以在后面的實(shí)際應(yīng)用中再深刻理解它。
- Redis入門指南(第3版)
- C語言程序設(shè)計立體化案例教程
- Mastering Swift 2
- Reactive Programming With Java 9
- Big Data Analytics
- GeoServer Beginner's Guide(Second Edition)
- 小學(xué)生C++創(chuàng)意編程(視頻教學(xué)版)
- 微信小程序全棧開發(fā)技術(shù)與實(shí)戰(zhàn)(微課版)
- 零基礎(chǔ)學(xué)Kotlin之Android項目開發(fā)實(shí)戰(zhàn)
- Beginning C++ Game Programming
- R語言數(shù)據(jù)可視化:科技圖表繪制
- 寫給程序員的Python教程
- 零基礎(chǔ)學(xué)Python編程(少兒趣味版)
- Arduino機(jī)器人系統(tǒng)設(shè)計及開發(fā)
- 軟件測試項目實(shí)戰(zhàn)之功能測試篇