文章目录
- 可选参数
- 命名可选参数
- 位置可选参数
- 默认参数值
- main() 函数
- 函数是一等对象
- 匿名函数
- 返回值
Dart 是一门真正面向对象的语言, 甚至其中的函数也是对象,并且有它的类型 Function 。 这也意味着函数可以被赋值给变量或者作为参数传递给其他函数。 也可以把 Dart 类的实例当做方法来调用。
已下是函数实现的示例:
bool isNoble(int atomicNumber) { return _nobleGases[atomicNumber] != null; }
虽然在 Effective Dart 中推荐 公共API中声明类型, 但是省略了类型声明,函数依旧是可以正常使用的:
isNoble(atomicNumber) { return _nobleGases[atomicNumber] != null; }
如果函数中只有一句表达式,可以使用简写语法:
bool isNoble(int atomicNumber) => _nobleGases[atomicNumber] != null; => expr 语法是 { return expr; } 的简写。 => 符号 有时也被称为 箭头 语法。
提示: 在箭头 (=>) 和分号 ( ; ) 之间只能使用一个 表达式 ,不能是 语句 。 例如:不能使用 if 语句 ,但是可以是用 条件表达式.
函数有两种参数类型: required 和 optional。 required 类型参数在参数最前面, 随后是 optional 类型参数。 命名的可选参数也可以标记为 “@ required” 。 参考下一章节,了解更多细节。
可选参数
可选参数可以是命名参数或者位置参数,但一个参数只能选择其中一种方式修饰。
命名可选参数
调用函数时,可以使用指定命名参数
paramName: value。 例如:
enableFlags(bold: true, hidden: false);
定义函数是,使用
{param1, param2, …}来指定命名参数:
/// Sets the [bold] and [hidden] flags ...
void enableFlags({bool bold, bool hidden}) {...}
Flutter 创建实例的表达式可能很复杂, 因此窗口小部件构造函数仅使用命名参数。 这样创建实例的表达式更易于阅读。
使用
@required注释表示参数是 required 性质的命名参数, 该方式可以在任何 Dart 代码中使用(不仅仅是Flutter)。
const Scrollbar({Key key, @required Widget child})
此时 Scrollbar 是一个构造函数, 当 child 参数缺少时,分析器会提示错误。
Required 被定义在
meta package。 无论是直接引入(import)
package:meta/meta.dart,或者引入了其他 package,而这个 package 输出(export)了
meta,比如 Flutter 的
package:flutter/material.dart。
位置可选参数
位置可选参数
将参数放到
[]中来标记参数是可选的:
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');
默认参数值
默认参数值
在定义方法的时候,可以使用 = 来定义可选参数的默认值。 默认值只能是编译时常量。 如果没有提供默认值,则默认值为 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 = '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');
list 或 map 可以作为默认值传递。 下面的示例定义了一个方法
doStuff(), 并分别指定参数
list和
gifts 的默认值。
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() 函数
任何应用都必须有一个顶级
main()函数,作为应用服务的入口。
main() 函数返回值为空,参数为一个可选的
List<String>。
下面是 web 应用的
main()函数:
void main() {
querySelector('#sample_text_id')
..text = 'Click me!'
..onClick.listen(reverseText);
}
提示:以上代码中的 … 语法为 级联调用 (cascade)。 使用级联调用, 可以简化在一个对象上执行的多个操作。
下面是一个命令行应用的
main() 方法,并且使用了输入参数:
// 这样运行应用: 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];
// 将 printElement 函数作为参数传递。
list.forEach(printElement);
同样可以将一个函数赋值给一个变量,例如:
var loudify = (msg) => '!!! ${msg.toUpperCase()} !!!';
assert(loudify('hello') == '!!! HELLO !!!');
示例中使用了匿名函数。 下一章节会有更多介绍。
匿名函数
匿名函数
多数函数是有名字的, 比如
main()和
printElement()。 也可以创建没有名字的函数,这种函数被称为 匿名函数, 有时候也被称为 lambda 或者 closure 。 匿名函数可以赋值到一个变量中, 举个例子,在一个集合中可以添加或者删除一个匿名函数。
匿名函数和命名函数看起来类似— 在括号之间可以定义一些参数或可选参数,参数使用逗号分割。
后面大括号中的代码为函数体:
([[Type] param1[, …]]) {
codeBlock;
};
下面例子中定义了一个包含一个无类型参数 item 的匿名函数。 list 中的每个元素都会调用这个函数,打印元素位置和值的字符串。
var list = ['apples', 'bananas', 'oranges'];
list.forEach((item) {
print('${list.indexOf(item)}: $item');
});
如果函数只有一条语句, 可以使用箭头简写。两个函数是等价的。
list.forEach(
(item) => print('${list.indexOf(item)}: $item'));
返回值
返回值
所有函数都会返回一个值。 如果没有明确指定返回值, 函数体会被隐式的添加
return null;语句。
foo() {}
assert(foo() == null);