Dart是一种完全面向对象的语言,即使函数也是对象,也有类型。这意味着函数可以被赋值给变量或作为参数传递给其他函数。
下面是一个实现方法的实例:
int add(int a, int b) { return a + b;}
对于只包含一个表达式的函数,可以使用简写语法:
int add(int a, int b) => a + b;
=> expr 的语法是 { return expr; }, =>语法有时被称为箭头语法。
一个方法可以有任意数量参数,后面可以跟着命名参数,也可以跟着可选参数(但不能两者都跟着)
在定义函数时,使用{param1, param2,…}来指定命名参数。
命名参数是可选的,除非它们被显式地标记为required。
//定义void enableFlags({bool? bold, bool? hidden}) {...}//调用enableFlags(bold: true, hidden: false);
虽然命名参数是一种可选参数,但是可以用required注释它们,以表明该参数是强制性的—用户必须为该参数提供一个值。例如
const Scrollbar({super.key, required Widget child});
如果有人试图在没有指定child参数的情况下创建Scrollbar,那么分析器将报错。
在[]中包装一组函数参数将它们标记为可选参数,如下:
//定义一个函数方法,同时定义device是可选的参数String say(String from, String msg, [String? device]) { var result = '$from says $msg'; if (device != null) { result = '$result with a $device'; } return result;}//不设置device参数assert(say('Bob', 'Howdy') == 'Bob says Howdy');//设置device参数assert(say('Bob', 'Howdy', 'smoke signal') == 'Bob says Howdy with a smoke signal');
函数可以使用=为可选参数定义默认值,包括命名参数和位置参数。默认值必须是编译时常量,如果参数没有设置默认值,则默认为null。
下面是一个为命名参数设置默认值的示例:
/// 定义函数方法,并为bold和hidden设置默认值void enableFlags({bool bold = false, bool hidden = false}) {...}// 调用函数,bold = true; hidden=false.enableFlags(bold: true);
下面的例子展示了如何为位置参数设置默认值:
String say(String from, String msg, [String device = 'Android']) { var result = '$from says $msg with a $device'; return result;}assert(say('Bob', 'Hello') == 'Bob says Hello with a Android');
还可以将List或Map作为默认值传递。下面的示例定义了一个函数doStuff(),它为list形参指定了一个默认List,并为gifts形参指定了一个默认Map:
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');}
每个应用程序必须有一个顶级的main()函数,它作为应用程序的入口点。main()函数返回void,并有一个可选的List<String>参数作为参数。如下:
void main() { print('Hello, World!');}
接受参数的main函数:
void main(List<String> arguments) { print(arguments); assert(arguments.length == 2); assert(int.parse(arguments[0]) == 1); assert(arguments[1] == 'test');}
函数是Dart头等对象。
可以将一个函数作为参数传递给另一个函数。例如:
void printElement(int element) { print(element);}var list = [1, 2, 3];//将printElement做为一个参数传递.list.forEach(printElement);
还可以将函数赋值给变量,例如
var loudify = (msg) => '!!! ${msg.toUpperCase()} !!!';assert(loudify('hello') == '!!! HELLO !!!');
大多数函数都是命名的,比如main()或上面定义的printElement()。还可以创建一个称为匿名函数的匿名函数,有时也可以创建lambda或闭包。可以将匿名函数赋给一个变量。
匿名函数看起来类似于命名函数——圆括号中有0个或多个参数,由逗号和可选类型分隔。
下面的代码块包含函数体:
([[Type] param1[, …]]) {
codeBlock;
};
下面的示例定义了一个匿名函数,其参数为未指定具体类型的item。对列表中的每一项调用该函数,将打印一个包含指定索引处值的字符串。
const list = ['apples', 'bananas', 'oranges'];list.forEach((item) { print('${list.indexOf(item)}: $item');});
该函数只包含一个表达式或返回语句,可以使用箭头表示法缩短它:
list.forEach((item) => print('${list.indexOf(item)}: $item'));
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); } }}
闭包是一个函数对象,它可以访问其作用域内的变量,即使该函数在其作用域之外使用。
Function makeAdder(int addBy) { return (int 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);}
所有函数都返回一个值。如果没有指定返回值,语句返回null。
foo() {}assert(foo() == null);int foo() { return 1;}assert(foo() == 1);