(四)Dart操作符、代码注释
一、Operators(操作符)
注:expr
为表达式,操作符的优先级在下表中自上而下的顺序由高到低。
描述 | 操作符 |
---|---|
一元后缀 | expr++ expr-- () [] . ?.
|
一元前缀 | -expr ! expr ~ expr ++ expr -- expr |
乘法类型 |
* / % ~/
|
加法类型 |
+ -
|
移动 位运算 |
<< >>
|
与 位运算 |
& |
异或 位运算 |
^ |
或 位运算 |
| |
关系和类型测试 |
>= > <= < as is is!
|
等式 |
== !=
|
逻辑与 | && |
逻辑或 | || |
空值判断 | ?? |
条件 | expr1 ? expr2 : expr3 |
级联 | .. |
赋值 |
= *= /= ~/= %= += -= <<= >>= &= ^= |= ??=
|
1.1. Arithmetic operators(算术操作符)
操作符 | 解释 |
---|---|
+ | 加号 |
- | 减号 |
- expr |
负号 |
* | 乘号 |
/ | 除号 |
~/ | 除号,但是返回值为整数 |
% | 取模 |
var a = 20 ~/ 5;
var b = 20 ~/ 3;
var c = 20 ~/ 3.0;
/*
Dart是强语法类型,报错:A value of type 'double'
cant't be assigned to a variable of type 'int'.
*/
int d = 20 / 3;
/*
可以调用toInt()强制类型转换,但是不建议使用,编译器会提示:
The operator x ~/ y is more efficient than (x / y).toInt().
*/
int e = (20 / 3).toInt();
print(a); // 4
print(b); // 6
print(c); // 6
print(e); // 6
Dart 还支持递增、递减前缀 和后缀操作:
操作符 | 解释 |
---|---|
++var |
var = var + 1 (expression value is var + 1 ) |
var++ |
var = var + 1 (expression value is var ) |
--var |
var = var – 1 (expression value is var – 1 ) |
var-- |
var = var – 1 (expression value is var ) |
1.2.Equality and relational operators(相等相关的操作符)
注:要测试两个对象代表的是否为同样的内容,使用
==
操作符。(在某些情况下,你需要知道两个对象是否是同一个对象, 使用identical()
方法。)
操作符 | 解释 |
---|---|
== |
相等 |
!= |
不等 |
> |
大于 |
< |
小于 |
>= |
大于等于 |
<= |
小于等于 |
List list1 = List();
List list2 = List();
Map map = Map();
Object a = List();
Object b = List();
int c = 2;
int d = 6;
int h = 2;
print(identical(list1, map)); // false
print(identical(list1, list2)); // false
print(identical(c, d)); // false
print(identical(a, b)); // false
print(identical(c, h)); // true
// 为什么 c和h是同一个对象?因为HashCode相同!
print(identityHashCode(c)); // 2
print(identityHashCode(h)); // 2
1.3. Type test operators(类型判定操作符)
as
、is
、和is!
操作符是在运行时判定对象 类型的操作符:
操作符 | 解释 |
---|---|
as | 类型转换 |
is | 如果对象是指定的类型返回 True |
is! | 如果对象是指定的类型返回 False |
只有当 obj
实现了 T
的接口, obj is T
才是 true
。例如 obj is Object
总是 true
。
使用 as
操作符把对象转换为特定的类型。 一般情况下,你可以把它当做用 is
判定类型然后调用所判定对象的函数的缩写形式。例如下面的示例:
/ *
注意: 下面这两个代码效果是有区别的。如果 emp 是 null 或者不是 Person 类型,
则使用 is 则不会执行条件里面的代码,而使用 as 则会抛出一个异常。
*/
if (emp is Person) { // 类型检查
emp.firstName = 'Bob';
}
// 使用 as 操作符可以简化上面的代码:
(emp as Person).firstName = 'Bob';
1.4. Assignment operators(赋值操作符)
使用=
操作符来赋值。 但是还有一个 ??=
操作符用来指定 值为 null
的变量的值。
操作符 | 操作符 | 操作符 | 操作符 | 操作符 | 操作符 |
---|---|---|---|---|---|
= |
–= |
/= |
%= |
>>= |
^= |
+= |
*= |
~/= |
<<= |
&= |
|= |
下面是复合赋值操作符工作原理解释:
复合赋值操作符 | 相等的表达式 | |
---|---|---|
对于 操作符 op: | a op= b |
a = a op b |
示例: | a += b |
a = a + b |
int a = 7; // 给 a 变量赋值
/*
如果 b 是 null,则赋值给 b;如果不是 null,则 b 的值保持不变
*/
int b = 1;
b ??= 9;
// 使用 ??= 前,变量c一定要先声明或者声明且赋值的,否则编译器报错
int c ??= 9;
1.5.Logical operators(逻辑操作符)
操作符 | 解释 |
---|---|
!expr |
对表达式结果取反(true 变为 false ,false 变为 true) |
|| |
逻辑或 |
&& |
逻辑与 |
1.6.Bitwise and shift operators(位和移位操作符)
操作符 | 解释 |
---|---|
& |
AND(与) |
| |
OR(或) |
^ |
XOR(异或) |
~expr |
Unary bitwise complement (0s become 1s; 1s become 0s)(一元位补码( 0s变为1s;1s变为0s )) |
<< |
Shift left(左移) |
>> |
Shift right(右移) |
final value = 0x22;
final bitmask = 0x0f;
assert((value & bitmask) == 0x02); // 与
assert((value & ~bitmask) == 0x20); // 与非
assert((value | bitmask) == 0x2f); // 或
assert((value ^ bitmask) == 0x2d); // 异或
assert((value << 4) == 0x220); // 左移
assert((value >> 4) == 0x02); // 右移
1.7.Conditional expressions(条件表达式)
Dart有两个运算符,可让您简明地评估可能需要if-else
语句的表达式:
condition ? expr1 : expr2
如果条件为真,返回expr1,否则返回expr2
expr1 ?? expr2
如果expr1为非空,则返回其值;否则,计算并返回expr2的值。
- 如果你需要根据布尔表达式赋值时,考虑使用
?:
var isHidden = (3 > 2) ? true : false;
- 如果布尔表达式测试为空,考虑使用
??
String studentName(String name) => msg ?? 'Tom';
// 非常长的使用if - else语句的版本
String studentName(String name) {
if (name != null) {
return name;
} else {
return 'Tom';
}
1.8.Cascade notation (..)(级联操作符)
级联操作符 (..
) 可以在同一个对象上连续调用多个函数以及访问成员变量。 使用级联操作符可以避免创建临时变量,并且写出来的代码看起来更加流畅:
querySelector('#confirm') // 获取一个对象
..text = 'Confirm' // 使用它的成员
..classes.add('important')
..onClick.listen((e) => window.alert('Confirmed!'));
第一个方法 querySelector()
返回了一个 selector
对象。 后面的级联操作符都是调用这个对象的成员, 并忽略每个操作所返回的值。
上面的代码和下面的代码功能一样:
var button = querySelector('#confirm');
button.text = 'Confirm';
button.classes.add('important');
button.onClick.listen((e) => window.alert('Confirmed!'));
级联调用也可以嵌套:
final addressBook = (AddressBookBuilder()
..name = 'jenny'
..email = 'jenny@example.com'
..phone = (PhoneNumberBuilder()
..number = '415-555-0100'
..label = 'home')
.build())
.build();
无法在 返回值为void
上使用级联操作符:
var sb = StringBuffer();
// sb.write() 函数返回一个 void, 无法在 void 上使用级联操作符。
sb.write('foo')
..write('bar'); // 错误:没有为“void”定义的方法“write”。
注意: 严格来说, 两个点的级联语法不是一个操作符。 只是一个 Dart 特殊语法。
1.9.Other operators(其他操作符)
操作符 | 名称 | 含义 |
---|---|---|
() |
使用方法 | 代表调用一个方法 |
[] |
访问List
|
访问List 中特定位置的元素 |
. |
访问 Member | 访问元素,例如 foo.bar 代表访问 foo 的 bar 成员 |
?. |
条件成员访问 | 和 . 类似,但是左边的操作对象可以为 null ,例如 foo?.bar 如果foo 为 null 则返回 null ,否则返回 bar 成员 |
var str1 = "hello world";
var str2 = null;
print(str1?.length); // 11
print(str2?.length); // null,此语法类似swift语言中的Optional(?.)
print(str2.length); // 报错
二、代码注释
Dart 支持单行注释、多行注释和 文档注释。
- 单行注释以
//
开始。//
后面的一行内容 为 Dart 代码注释。
// 打印 ff
print('ff');
- 多行注释以
/*
开始,*/
结尾。 多行注释 可以 嵌套。
/*
* This is a lot of work. Consider raising chickens.
Llama larry = new Llama();
larry.feed();
larry.exercise();
larry.clean();
*/
- TODO注释
// TODO: refactor into an AbstractLlamaGreetingFactory?
print('Welcome to my Llama farm!');
- 文档注释
文档注释可以使用 ///
开始, 也可以使用 /**
开始 并以 */
结束。
在文档注释内, Dart 编译器忽略除了[]
以外的内容。 使用[]
引用 classes
、 methods
、 fields
、 top-level variables
、 functions
、 和 parameters
。[]
里面的名字使用 当前注释出现地方的语法范围查找对应的成员(在简书markdown中,[]
中的内容无法高亮显示和点击查询跳转,有些遗憾,但在例如:WebStorm、装有支持Dart IDE的插件开发工具中可以体现)。
class Food {
}
class Activity {
}
/// A domesticated South American camelid (Lama glama).
///
/// Andean cultures have used llamas as meat and pack
/// animals since pre-Hispanic times.
class Llama {
String name;
/// Feeds your llama [Food].
///
/// The typical llama eats one bale of hay per week.
void feed(Food food) {
// ...
}
/// Exercises your llama with an [activity] for
/// [timeLimit] minutes.
void exercise(Activity activity, int timeLimit) {
// ...
}