這里開始講Dart語(yǔ)法中最重要的元素之一:方法,Dart里面的方法跟java還是有很大的不同
方法
Dart是一種真正的面向?qū)ο笳Z(yǔ)言,因此即使是函數(shù)也是對(duì)象并且具有類型Function。
這意味著函數(shù)可以分配給變量或作為參數(shù)傳遞給其他函數(shù)。
您也可以像調(diào)用函數(shù)一樣調(diào)用Dart類的實(shí)例。
bool isNoble(int atomicNumber) {
return _nobleGases[atomicNumber] != null;
}
bool isNoble(int atomicNumber) => _nobleGases[atomicNumber] != null;
這是一個(gè)標(biāo)準(zhǔn)的方法,其中返回類型是可以省略的,Dart會(huì)自動(dòng)推斷,而它下面的那個(gè)方法則是一個(gè)方法的簡(jiǎn)寫版
- 可選參數(shù)和必選參數(shù)
函數(shù)可以有兩種類型的參數(shù):必需和可選。首先列出所需參數(shù),然后列出任何可選參數(shù)。命名的可選參數(shù)也可以標(biāo)記為@required。當(dāng)我們調(diào)用一個(gè)方法的時(shí)候,我們可以給方法填上一個(gè)默認(rèn)值,例如:
//這是一個(gè)可選參數(shù)的的方法
optionalFunction({int a = 1 ,int b =2}){
return a+b;
}
//在調(diào)用的時(shí)候我可以選擇傳一個(gè)參數(shù),也可以選擇不傳
main(){
optionalFunction(a:4);
optionalFunction(a:4,b:1);
optionalFunction(4,1);//TODO 錯(cuò)誤?。。?!
optionalFunction();
}
注意,這個(gè)方法在調(diào)用的時(shí)候不能像kotlin一樣通過(guò)參數(shù)的順序來(lái)指定參數(shù),可選參數(shù)的方法傳參必須在前面加上方法的參數(shù)名,來(lái)指定參數(shù)的值
如果我在可選參數(shù)前面加上@Required注解,就表明在這一群可選參數(shù)中,這個(gè)參數(shù)是必傳項(xiàng),不去傳遞這個(gè)參數(shù)是非法的
optionalFunction({int a = 1 ,@required int b }){
return a+b;
}
optionalFunction(a:4); //非法。必須傳遞b的值
注意:@Required 注解需要導(dǎo)入外部包才能使用
可以直接導(dǎo)入包:meta / meta.dart,也可以導(dǎo)入另一個(gè)導(dǎo)出meta的包,例如Flutter的包:flutter / material.dart。
- 可選位置參數(shù)
可選位置參數(shù)的意思就是即使你不傳入這個(gè)參數(shù),也可以調(diào)用這個(gè)方法,在上面一個(gè)例子中我們發(fā)現(xiàn)
optionalFunction({int a = 1 ,int b =3 }){
return a+b;
}
這個(gè)方法,如果調(diào)用的時(shí)候是這樣調(diào)用的
optionalFunction(4);
這樣編譯是過(guò)不了的,系統(tǒng)不知道你這個(gè)4是a還是b
但是可選參數(shù)中這樣調(diào)用是可以的,即使你這個(gè)可選參數(shù)沒(méi)有默認(rèn)值,看代碼
String say(String from, String msg, [String device]) {
var result = '$from says $msg';
if (device != null) {
result = '$result with a $device';
}
return result;
}
assert(say('Bob', 'Howdy') == 'Bob says Howdy');
assert(say('Bob', 'Howdy', 'smoke signal') ==
'Bob says Howdy with a smoke signal');
在上面這個(gè)示例中,第三個(gè)參數(shù)device在第一次調(diào)用中是沒(méi)有傳遞的,但是編譯器沒(méi)有報(bào)錯(cuò),這就是可選位置參數(shù)與全部可選參數(shù)的區(qū)別
級(jí)聯(lián)表示法
級(jí)聯(lián)類似于java里面的build設(shè)計(jì)模式,可以通過(guò)單行一系列的語(yǔ)法操作一個(gè)對(duì)象
class Grammar2 {
var x, y, z;
}
var g2 = Grammar2();
g2 ..x = 1 ..y = 2..z=3;//這樣就完成了一系列的賦值
等價(jià)于
g2.x = 1; g2.y=2;g2.z=3;
querySelector('#sample_text_id')
..text = 'Click me!'
..onClick.listen(reverseText);
Functions as first-class objects(這個(gè)感覺(jué)翻譯成中文怪怪的)
你可以傳遞一個(gè)方法當(dāng)作一個(gè)參數(shù)傳遞給另一個(gè)方法
void printElement(int element) {
print(element);
}
var list = [1, 2, 3];
// Pass printElement as a parameter.
list.forEach(printElement);
上面這是一個(gè)簡(jiǎn)單版本的方法傳遞,這里延伸一下方法傳遞的概念Typedefs,java里面是沒(méi)有方法當(dāng)作參數(shù)的概念的,Dart將這個(gè)玩的很6,我們看看Typedefs
Typedefs
在Dart中,函數(shù)是對(duì)象,就像string和int一樣,typedef或?yàn)楹瘮?shù)類型提供了在聲明字段和返回類型時(shí)可以使用的名稱。當(dāng)函數(shù)類型分配給變量時(shí),typedef會(huì)保留類型信息。
class SortedCollection {
Function compare;
SortedCollection(int f(Object a, Object b)) {
compare = f;
}
}
// Initial, broken implementation.
int sort(Object a, Object b) => 0;
void main() {
SortedCollection coll = SortedCollection(sort);
// All we know is that compare is a function,
// but what type of function?
assert(coll.compare is Function);
}
上面這種是普通的方法傳遞的代碼,就跟注釋上面的疑問(wèn)一樣,都知道這個(gè)傳遞進(jìn)來(lái)的f是一個(gè)方法,但是是什么類型的方法呢?
這個(gè)時(shí)候typedef就派上用場(chǎng)了將f分配給比較時(shí),類型信息會(huì)丟失。f的類型是(Object,Object)→int(其中→表示返回),但比較的類型是Function。
如果我們將代碼更改為使用顯式名稱并保留類型信息,則開發(fā)人員和工具都可以使用該信息。
typedef Compare = int Function(Object a, Object b); //typedef關(guān)鍵字需要定義在class的外圍
class SortedCollection {
Compare compare;
SortedCollection(this.compare);
}
// Initial, broken implementation.
int sort(Object a, Object b) => 0;
void main() {
SortedCollection coll = SortedCollection(sort);
assert(coll.compare is Function);
assert(coll.compare is Compare);
}
也可以增加泛型
typedef Compare<T> = int Function(T a, T b);
int sort(int a, int b) => a - b;
void main() {
assert(sort is Compare<int>); // True!
}
方法的注解
Dart常用的有@override和@deprecated意思跟java一樣,這里略過(guò)
匿名方法
也稱作為無(wú)名方法,顧名思義,就是這個(gè)方法沒(méi)有方法名,其他的跟普通方法一樣。舉個(gè)例子:如果我們初始化一個(gè)值ax,這個(gè)ax的值需要從一個(gè)方法的返回值中拿到,在java里面我們這么做
int ax = getAx(9);
int getAx(int a){
return a *2;
}
Dart中是這樣的
var ax = (a) => a2;
是不是簡(jiǎn)潔了很多?那么無(wú)名方法在哪里呢?就是這個(gè)(a)=>a2這個(gè)方法除了沒(méi)有名字,其他跟上面的一樣
第二個(gè)應(yīng)用場(chǎng)景就是有些方法需要你傳遞一個(gè)方法進(jìn)去,第一種辦法是上面我們例子說(shuō)的,定義一個(gè)普通方法傳遞進(jìn)去
int sort(Object a, Object b) {
......
}
functionPass(sort); //普通方法
//無(wú)名的寫法是這樣的
void functionPass((Object a, Object b){
.......
})
//更加常用的地方的是
var list = ['apples', 'bananas', 'oranges'];
list.forEach((item) {
print('${list.indexOf(item)}: $item');
});
方法的返回值
這里單獨(dú)提一下方法的返回值,默認(rèn)情況下dart的方法不寫返回值不代表沒(méi)有返回值,他的返回值是null
foo() {}
assert(foo() == null);
未完待續(xù)~~~~~