愿你坚持不懈,努力进步,进阶成自己理想的人

—— 2017.09, 写给3年后的自己

Dart学习笔记(三):运算符

Dart的操作符

Dart中的操作符和大多数编程语言所差无几,但是也有一些特定的操作符。此外,Dart的操作符是 可以重载 的,以下列出的则是Dart的操作符优先级(从上到下,从左到右,优先级依次变小):

  • 一元后缀:expr++expr--()[].?
  • 一元前缀:-expr!expr~expr++expr--expr
  • 乘除运算符:*/%~/(这个是Dart特有的运算符)
  • 加减运算符:+-
  • 位移运算符:<<>>
  • 按位与:&
  • 按位异或:^
  • 按位或:|
  • 关系与类型测试:>=><=<asisis!
  • 等价性:==!=
  • 逻辑与:&&
  • 逻辑或:||
  • null判断:??
  • 条件表达式:expr1 ? expr2 : expr3
  • 级联运算符:..
  • 赋值运算符:=*=/=~/=%=+=-=<<=>>=&=^=|=??=

其中一些Dart独有的表达式,为:

1、除取整运算符~/

~/是除号,但是返回值是整数,如:

5 ~/ 2 == 2; // true

2、没有全等运算符

Dart中不像JavaScript有===,它只有==相等运算符,用以测试两个对象代表的是否为同样的内容,x == y的语义为:

  • 如果x或者ynull,如果两个都是null则返回true,如果只有一个是null则返回false
  • 返回如下函数的返回值:x.==(y)(也就是说,==是x的一个方法,测试相等性时,是将y传入==方法测试的,如果需要,甚至还可以覆写这些操作符
class A {
  bool operator ==(dynamic y) {
    return y == 1;
  }
}
  
main() {
  var a = new A();
  print(a == 1); // true
  print(a == 2); // false
}

3、类型判定运算符

Dart中有如下的类型判定运算符:

  • as:类型转换
  • is:如果对象是指定的类型,则返回true
  • is!:如果对象是指定的类型,返回false

只有当obj实现了T的接口时,obj is T才是true,如:obj is Object总是true,此外,可以用as运算符把对象转化为特定的类型,如:

(emp as Person).firstName = 'Bob';

4、??=运算符

对于x ??= y,具有如下的行为:

  • 如果xnull,则赋值yx
  • 如果x不是null,则不赋值yx
  • 不能用于变量初始化赋值
var x = null;
x ??= 10;
print(x); // 输出10

var y = 10;
y ??= 20;
print(y); // 输出10

4、??条件表达式

Dart中除了常规的大多数语言都支持的?:条件表达式之外,还有??条件表达式,即对于expr1 ?? expr2,执行如下运算:

  • 如果expr1不是null,则返回expr1
  • 如果expr1null,则执行expr2并返回

也就是说expr1 ?? expr2操作符等价于:expr1 == null ? expr2 : expr1

5、级联操作符

级联操作符..可以在同一个对象上连续调用多个函数以及访问成员变量,使用级联操作符可以避免创建临时变量,如:

querySelector('#button')
    ..text = 'Confirm'
    ..classes.add('important')
    ..onClick.listen((e) => window.alert('Confirmed!'));

它的功能与如下这段代码一致:

var button = querySelector('#button');
button.text = 'Confirm';
button.classes.add('important');
button.onClick.listen((e) => window.alert('Confirmed!'));

级联调用是可以嵌套的,如:

final addressBook = (
    new AddressBookBuilder()
    ..name = 'Ruphi'
    ..email = 'ruphi@ruphi.cn'
    ..phone = (
        new PhoneNumberBuilder()
        ..number = '12345678910'
        ..label = 'Home'
    ).build()
).build();

但是需要注意的是,在方法上使用级联操作符需要小心,如以下代码是错误的:

var str = new StringBuffer();
str.write('foo')..write('bar');

这是因为,write()方法返回的是void,无法在void上使用级联运算符,正确的写法应该是:

str..write('foo')..write('bar');

6、条件成员访问?.

条件成员访问符?.,要求对于obj?.propertyOrMethod操作满足:

  • obj不能是null
  • 如果objnull,则返回null;如果不是null,则返回obj.propertyOrMethod