函数
Dart 是一门真正面向对象的语言, 甚至其中的函数也是对象 。 这也意味着函数可以被赋值给变量或者作为参数传递给其他函数。 也可以把 Dart 类的实例当做方法来调用。
以下是函数实现的示例:
bool isNoble(int atomicNumber) {
return _nobleGases[atomicNumber] != null;
}
如果函数中只有一句表达式,可以使用简写语法:
bool isNoble(int atomicNumber) => _nobleGases[atomicNumber] != null;
函数有两种参数类型: required 和 optional。 required 类型参数在参数最前面, 随后是 optional 类型参数。 命名的可选参数也可以标记为 “@ required” 。
可选参数
可选参数可以是命名参数或者位置参数,但一个参数只能选择其中一种方式修饰。
位置可选参数
将参数放到 []
中来标记参数是可选的:
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 可以作为默认值传递。
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() 函数返回值为空,参数为一个可选的 List 。
函数作为参数
一个函数可以作为另一个函数的参数。例如:
void printElement(int element) {
print(element);
}
var list = [1, 2, 3];
// 将 printElement 函数作为参数传递。
list.forEach(printElement);
同样可以将一个函数赋值给一个变量,例如:
var loudify = (msg) => '!!! ${msg.toUpperCase()} !!!';
assert(loudify('hello') == '!!! HELLO !!!');
匿名函数
没有名字的函数,这种函数被称为 匿名函数, 有时候也被称为 lambda
或者 closure
。
下面例子中定义了一个包含一个无类型参数 item 的匿名函数。 list 中的每个元素都会调用这个函数,打印元素位置和值的字符串。
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'));
运算符
算术运算符
Dart 支持常用的运算符示例:
assert(2 + 3 == 5);
assert(2 - 3 == -1);
assert(2 * 3 == 6);
assert(5 / 2 == 2.5); // 结果是双浮点型
assert(5 ~/ 2 == 2); // 结果是整型
assert(5 % 2 == 1); // 余数
assert('5/2 = ${5 ~/ 2} r ${5 % 2}' == '5/2 = 2 r 1');
Dart 还支持前缀和后缀,自增和自减运算符。示例:
var a, b;
a = 0;
b = ++a; // a自加后赋值给b。
assert(a == b); // 1 == 1
a = 0;
b = a++; // a先赋值给b后,a自加。
assert(a != b); // 1 != 0
a = 0;
b = --a; // a自减后赋值给b。
assert(a == b); // -1 == -1
a = 0;
b = a--; // a先赋值给b后,a自减。
assert(a != b); // -1 != 0
关系运算符
要测试两个对象x和y是否表示相同的事物, 使用 == 运算符。 (在极少数情况下, 要确定两个对象是否完全相同,需要使用 identical()
函数。)
示例:
assert(2 == 2);
assert(2 != 3);
assert(3 > 2);
assert(2 < 3);
assert(3 >= 3);
assert(2 <= 3);
类型判定运算符
as, is, 和 is!
运算符用于在运行时处理类型检查。
使用 as 运算符将对象强制转换为特定类型。 通常,可以认为是 is 类型判定后,被判定对象调用函数的一种缩写形式。
if (emp is Person) {
// Type check
emp.firstName = 'Bob';
}
使用 as 运算符进行缩写:
(emp as Person).firstName = 'Bob';
提示: 以上代码并不是等价的。 如果 emp 为 null 或者不是 Person 对象, 那么第一个 is 的示例,后面将不回执行; 第二个 as 的示例会抛出异常。
赋值运算符
使用 = 为变量赋值。 使用 ??= 运算符时,只有当被赋值的变量为 null 时才会赋值给它。
// 将值赋值给变量a
a = value;
// 如果b为空时,将变量赋值给b,否则,b的值保持不变。
b ??= value;
条件表达式
Dart有两个运算符,有时可以替换 if-else 表达式, 让表达式更简洁:
- condition ? expr1 : expr2
如果条件为 true, 执行 expr1 (并返回它的值): 否则, 执行并返回 expr2 的值。
var visibility = isPublic ? 'public' : 'private';
- expr1 ?? expr2
如果 expr1 是 non-null, 返回 expr1 的值; 否则, 执行并返回 expr2 的值。
String playerName(String name) => name ?? 'Guest';
级联运算符 (…)
级联运算符 (…) 可以实现对同一个对像进行一系列的操作。 除了调用函数, 还可以访问同一对象上的字段属性。
querySelector('#confirm') // 获取对象。
..text = 'Confirm' // 调用成员变量。
..classes.add('important')
..onClick.listen((e) => window.alert('Confirmed!'));
上面的代码等价于:
var button = querySelector('#confirm');
button.text = 'Confirm';
button.classes.add('important');
button.onClick.listen((e) => window.alert('Confirmed!'));