Flutter Dart 级联操作符..

15 min read

什么是级联运算符..

class Model {
  String hello(String name) {
    var value = 'hello $name';
    print(value);
    return value;
  }

  void sayHi(String name) {
    print("hi $name");
  }

  void sayGoodbye(String name) {
    print('goodbye $name');
  }
}

// 针对`Model`类基本的用法是:
var model = Model()
model.hello('world')
model.sayHi('bill')
model.sayGoodbye('bill');

// 但是dart提供了更加简便的打开方式,级联(..)
// 下面的代码等效于上面的传统调用方式。
var model = Model()
  ..hello('world')
  ..sayHi('bill')
  ..sayGoodbye('bill');

级联操作符..在各种类型上的实践

  • 自定义类
  • 数组(列表List)
  • 字典(Map)
  • 字符串和StringBuffer
  • 异步方法
void main() {
  // 针对自定义类的调用,中规中矩
  // 需要注意的是`hello()`方法,它有返回值,但是级联调用后
  // 返回值丢失了
  var model = Model()
    ..hello('world')
    ..sayHi('bill')
    ..sayGoodbye('bill');
  /*
   output:
   hello world
   hi bill
   goodbye bill
   */

  // 针对列表的级联
  List<int> listInt = List()
    ..add(0)
    ..add(1)
    ..add(2)
    ..removeAt(1);
  print(listInt); // output: [0, 2]

  // 针对字典的级联
  Map<String,dynamic> aMap = Map()
    ..putIfAbsent('name', ()=>'bill')
    ..putIfAbsent('name', ()=>'gate')
    ..addAll({'sex':'male', 'age':1})
    ..remove('age');
  print(aMap); // output: {name: bill, sex: male}

  // 一个Bug示范:对字符串的级联add,add结果均抛弃了
  // 最后输出的是原字符串
  String aStr = ''
    ..add('line1\\n')
    ..add('line2\\n')
    ..add('line3');
  print('aStr:${aStr}_${aStr.length}'); // output: aStr:_0

  // 可变字符串的正确打开方式
  StringBuffer aStr2 = StringBuffer()
    ..write('hello ')
    ..write('world');
  print('aStr2:${aStr2}_${aStr2.length}'); // aStr2:hello world_11

  // 对异步方法处理
  // 由于异步方法的触发并需要特殊条件,所以级联调用跟普通方法一样
  // 区别是异步方法仍然会异步执行,某段时间后才会执行。
  class Model {
  	..
  	Future<void> asyncSayHi(String name) {
    		return Future.delayed(Duration(seconds: 1), (){
    	    		print('say hi from future $name');
    		});
 	 }
  }

  var model1 = Model()
    ..hello('world')
    ..sayHi('bill')
    ..sayGoodbye('bill')
    ..asyncSayHi('bill');
  // output:
  // hello world
  // hi bill
  // goodbye bill
  // ..(其他输出)
  // say hi from future bill

  // 目前的使用场景-解析json到对象
  static Attachment json2Attachment(dynamic json) {
    if (json == null || json is Map == false) { return null; }

    var result =  Attachment()
      ..id = '${json["id"]}'
      ..filename = json["filename"]
      ..contentId = json["contentId"]
      ..contentType = json["contentType"]
      ..encoding = json["encoding"]
      ..estimateSize = json["estimateSize"]
      ..contentLength = json["contentLength"]
      ..inlined = json["inlined"]
      ..type = json["type"];
    return result;
  }
  1. 使用级联让代码更简洁。
  2. 建议对void方法使用级联(注意丢失返回值的问题)。