學(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,如果expr1是null,則返回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';
如果emp為null或者不是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è)簡單的+和-重載的例子,其他的用法還蠻多,==的重載還要涉及到hash和isEqual吧,這個(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;
}