初次翻譯,部分內容並非按字面翻譯,是按本人理解進行了內容重組。如有錯誤望指正。 Dart是完全的面向對象的語言,甚至函數也是一個Function類型的對象。這意味著函數可以賦值給變數或者作為函數的參數。你可以直接用變數名(其實現了Function類)作為函數名直接調用。 參考如下示例代碼: 下麵是一 ...
- 初次翻譯,部分內容並非按字面翻譯,是按本人理解進行了內容重組。如有錯誤望指正。
Dart是完全的面向對象的語言,甚至函數也是一個Function類型的對象。這意味著函數可以賦值給變數或者作為函數的參數。你可以直接用變數名(其實現了Function類)作為函數名直接調用。
參考如下示例代碼:
/*如果類實現了call方法,它可以當成Function直接調用*/
class WannabeFunction {
call(String a, String b, String c) => '$a $b $c!';
}
main() {
var wf = new WannabeFunction();
var out = wf("Hi","there,","gang");
print('$out');
下麵是一個函數寫法的示例:
bool isNoble(int atomicNumber) {
return _nobleGases[atomicNumber] != null;
}
儘管Dart要求public的API需要說明返回類型,但是未明確指定返回類型的函數也是可以正常運行的
isNoble(atomicNumber) {
return _nobleGases[atomicNumber] != null;
}
For functions that contain just one expression, you can use a shorthand syntax:
如果函數體只包含一條語句的代碼塊,你可以用如下簡略寫法:
bool isNoble(int atomicNumber) => _nobleGases[atomicNumber] != null;
The => expr syntax is a shorthand for { return expr; }. The => notation is sometimes referred to as arrow syntax.
註意:必須是一條語句的代碼塊,可以放在=>和;之間。
函數由兩種參數類型:必須和可選。一般必須參數寫在前面,可選參數緊隨其後。
Optional parameters 可選參數
可選參數定義方式是位置型和命名型兩種二選一。
可選命名參數定義時,你可以指定參數名和參數預設值,如下所示:
enableFlags(bold: true, hidden: false);
當定義函數時,也可以用{param1, param2, …} 來描述命名參數。如下所示:
/// Sets the [bold] and [hidden] flags ...
void enableFlags({bool bold, bool hidden}) {...}
Flutter的對象初始化方法入參是複合型的,所以組件可以用命名參數的寫法準確映射到各個欄位。
你可以對命名參數添加@required,那麼它就變為一個必須參數。
const Scrollbar({Key key, @required Widget child})
When a Scrollbar is constructed, the analyzer reports an issue when the child argument is absent.
@required在meta的包中定義,使用時,需要引入import package:meta/meta,獲取其它包,其中包含了export meta的定義。
Optional positional parameters 可選位置參數
在[]中定義的參數被稱為位置型參數。
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');
Default parameter values 參數預設值
你可以用=給命名參數或者位置參數賦預設值。其中,預設值必須是常量。如果參數沒有定義預設值,其預設為null
下麵是命名參數的預設值寫法
/// Sets the [bold] and [hidden] flags ...
void enableFlags({bool bold = false, bool hidden = false}) {...}
// bold will be true; hidden will be false.
enableFlags(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;
}
assert(say('Bob', 'Howdy') ==
'Bob says Howdy with a carrier pigeon');
你也可以給預設值賦值lists或者maps,下麵就是這樣的例子:
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');
}
The main() function 主函數
每個應用都會有主函數,作為程式運行的入口。main函數就是Dart的主函數,它的返回值是void,入參是一個字元串數組。
void main() {
querySelector('#sample_text_id')
..text = 'Click me!'
..onClick.listen(reverseText);
}
註意:..是對象的鏈式調用的寫法。
下麵是一個帶有參數的main函數:
// Run the app like this: dart args.dart 1 test
void main(List<String> arguments) {
print(arguments);
assert(arguments.length == 2);
assert(int.parse(arguments[0]) == 1);
assert(arguments[1] == 'test');
}
你可以用args庫來解析命令行參數。
Functions as first-class objects 函數型參數
你可以使用函數作為一個入參傳遞給另一個函數。如下麵例子:
void printElement(int element) {
print(element);
}
var list = [1, 2, 3];
// Pass printElement as a parameter.
list.forEach(printElement);
你可以函數定義為變數,如下麵所示:
var loudify = (msg) => '!!! ${msg.toUpperCase()} !!!';
assert(loudify('hello') == '!!! HELLO !!!');
Anonymous functions 匿名函數
大部分函數都有函數名,比如main(),printElement(),你也可以定義一個無函數名的函數,可用lambda或者closure寫法,我們稱之為匿名函數。同時可以將匿名函數賦予一個變數來調用。匿名函數和命名函數一樣,都可以有0個或者更多的入參。如下示例所示:
([[Type] param1[, …]]) {
codeBlock;
};
下麵是一個具體示例:
var list = ['apples', 'bananas', 'oranges'];
list.forEach((item) {
print('${list.indexOf(item)}: $item');
});
如果函數體只是一個語句的代碼塊,你可以如下簡化,去除{}.
list.forEach(
(item) => print('${list.indexOf(item)}: $item'));
Lexical scope 辭彙作用域
Dart是一個lexically scoped language,意思是變數的作用域是和變數所以的代碼塊有關係,在變數所在代碼塊中,可以訪問到變數。
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);
}
}
}
Lexical closures 辭彙閉包
A closure is a function object that has access to variables in its lexical scope, even when the function is used outside of its original scope.
Functions can close over variables defined in surrounding scopes. In the following example, makeAdder() captures the variable addBy. Wherever the returned function goes, it remembers addBy.
/// Returns a function that adds [addBy] to the
/// function's argument.
Function makeAdder(num addBy) {
return (num i) => addBy + i;
}
void main() {
// Create a function that adds 2.
var add2 = makeAdder(2);
// Create a function that adds 4.
var add4 = makeAdder(4);
assert(add2(3) == 5);
assert(add4(3) == 7);
}
Testing functions for equality 測試函數的相等性
下麵是函數的頂層函數,靜態方法,對象方法的相等性
void foo() {} // A top-level function
class A {
static void bar() {} // A static method
void baz() {} // An instance method
}
void main() {
var x;
// Comparing top-level functions.
x = foo;
assert(foo == x);
// Comparing static methods.
x = A.bar;
assert(A.bar == x);
// Comparing instance methods.
var v = A(); // Instance #1 of A
var w = A(); // Instance #2 of A
var y = w;
x = w.baz;
// These closures refer to the same instance (#2),
// so they're equal.
assert(y.baz == x);
// These closures refer to different instances,
// so they're unequal.
assert(v.baz != w.baz);
}
Return values 返回值
所有函數都有返回值,如果沒有特別約定,返回值為null.這是編譯時,內置追加到函數體中。
foo() {}
assert(foo() == null);
- 第四篇準備翻譯 Operators操作符