Dart學習-方法
dart是一種真正面向物件的語言,所以函式也是物件,並且有一個型別、 Function
。這意味著函式可以分配給變數或者作為引數傳遞給其他函式。你也可以呼叫Dart類的例項,就像它是一個函式一樣。
下面是一個實現函式的例子:
bool isNoble(int atomicNumber) { return _nobleGases[atomicNumber] != null; }
雖然Effective Dart(作者推薦:dart的有效寫法)推薦公共API的型別註釋,但是如果省略以下型別,該函式仍然有效
isNoble(atomicNumber) { return _nobleGases[atomicNumber] != null; }
對於只包含一個表示式的函式,可以使用速記語法:
bool isNoble(int atomicNumber) => _nobleGases[atomicNumber] != null;
=> expr
語法是 {return expr;}
。 =>
符號有時被稱為箭頭語法。
注意:只有表示式(而不是語句!)可以存在於箭頭 ( => )
和分號 (;)
之間。 例如,你不能使用if語句,但可以用條件表示式。
函式可以有兩種型別的引數:必需引數和可選引數。首先列出所需引數,然後列出任何可選引數。命名的可選引數也可以標記為 @required
。
可選引數
可選引數可以是位置引數,也可以是命名引數,但不能同時是位置引數和命名引數。
1.可選命名引數
呼叫函式時,可以使用 paramName : value
指定命名引數。例如:
enableFlags(bold: true, hidden: false);
定義函式時,使用{ param 1,param 2,... }指定命名引數:
/// Sets the [bold] and [hidden] flags ... void enableFlags({bool bold, bool hidden}) {...}
Flutter
例項建立表示式可能會變得複雜,因此 Widget
建構函式專門使用命名引數。這使得例項建立表示式更容易閱讀。
你可以用 @required
註釋任何Dart程式碼中的命名引數(不僅僅是 Flutter
),以指示它是必需的引數。例如:
const Scrollbar({Key key, @required Widget child})
當 Scrollbar
被構建時,分析器會在缺少 child
引數時報錯。
Require
被定義在meta包裡。要麼直接匯入 package:meta/meta.dart
,要麼匯入另一個匯出 meta
包,如Flutter的 package:flutter/material.dart.
2.可選位置引數
在 []
中包裝一組函式引數,將它們標記為可選位置引數:
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');
3.預設引數值
函式可以使用 =
為命名引數和位置引數定義預設值。預設值必須是編譯時常量。如果未提供預設值,則預設值為null。
下面是為命名引數設定預設值的示例:
///設定bold預設值為true,實質hidden'預設值為false void enableFlags({bool bold = false, bool hidden = false}) {...} // bold為true; hidden為 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)
作為預設值傳遞。下面的示例定義了一個函式 doStuff()
,該函式指定了一個預設的 集合
來放置 list
引數和預設的 對映
來放置 gitfts
的引數
主函式
每個應用程式都必須有一個頂級 main()
函式,作為應用程式的入口點。 main()
函式返回void,並具有可選的 List<String>
作為引數。
下面是一個web應用程式的 main()
函式示例:
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 library
來定義和解析命令列引數。
方法作為一等物件
你可以將函式作為引數傳遞給另一個函式。例如:
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 !!!');
匿名函式
大多數函式都是命名的,例如 main()
或 printElement()
。你也可以建立一個沒有名字函式( 匿名函式 ),有時也可以建立 lambda 或 閉包 。你可以將匿名函式分配給變數,因此你可以這樣,例如:可以從集合中新增或刪除它。
匿名函式看起來類似於命名函式——零個或多個引數,括號中用逗號和可選型別註釋隔開。
下面的程式碼塊包含函式的主體:
([[Type] param1[, …]]) { codeBlock; };
下面的示例使用非型別化引數 item
定義了一個匿名函式。為列表中的每個專案呼叫的函式會列印一個字串,其中包含指定索引處的值。
var list = ['apples', 'bananas', 'oranges']; list.forEach((item) { print('${list.indexOf(item)}: $item'); }); -------------------------------------------------- 0: apples 1: bananas 2: oranges
如果函式只包含一條語句,可以使用箭頭符號來縮短它。
list.forEach( (item) => print('${list.indexOf(item)}: $item')); -------------------------------------------------- 0: apples 1: bananas 2: oranges
作用域
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
。
/// 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); }
測試函式是否相等
下面是測試頂級函式、靜態方法和例項方法是否相等的示例:
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(); // Instance #1 of A var w = A(); // Instance #2 of A var y = w; x = w.baz; // 這些閉包指向同一例項 (#2), // 因此他們是相等的 assert(y.baz == x); // 這些閉包指向不同的例項 // 因此他們是相等的 assert(v.baz != w.baz); }
返回值
所有函式都返回值。如果未指定返回值,則語句返回 null
;隱式附加到函式體。
foo() {} assert(foo() == null);
PS:本文 整理
自官方文件,若有發現問題請致郵 ofollow,noindex">[email protected]