Flutter入门-Dart语法3-late、运算符、空安全

752 阅读4分钟

late

late关键字是Dart 2.12及更高版本中引入的一个特性,用于延迟初始化。它主要用于两种场景:非空类型的延迟初始化和显式的懒加载

非空类型的延迟初始化

在引入空安全特性之后,Dart要求所有的变量在使用前都必须初始化。然而,在某些情况下,我们可能无法在声明变量的同时初始化它,比如依赖于构造函数参数或者需要进行异步操作来获取初始值。这时,late关键字就派上了用场。通过late标记的变量,Dart允许你稍后初始化这个变量,同时确保在第一次使用前已被初始化,否则会抛出异常。

class MyClass {
  late String description;

  void setDescription(String desc) {
    description = desc;
  }
}

显式的懒加载

late还可用于变量的懒加载,即变量在第一次被访问时才进行初始化。这对于初始化开销较大的变量非常有用,可以在确实需要这些变量的时候才去创建它们,从而提高程序的性能。

class MyDatabase {
  late final HeavyDatabase _database = HeavyDatabase();

  HeavyDatabase get database => _database;
}

在这个例子中,_database变量只会在第一次访问database属性时被初始化,而不是在MyDatabase类的实例被创建时。

注意事项

  • 使用late时需要小心,因为如果在变量被正确初始化之前访问它,会抛出LateInitializationError异常。
  • late不应该被用作绕过空安全的手段。确保在第一次访问变量之前已经对其进行了初始化。
  • 对于懒加载的场景,考虑初始化开销和访问频率,决定是否使用late是一个好的选择。

运算符

基本运算符

dart中的基本运算符和其他语言区别不大,比较特殊的有一个检查两个引用是否指向同一个对象identical

// 赋值
 var a = 1;
 int? b;
 b ??= 2; // 如果 b 为空的话就把 2 赋值给 b
 a += 0; // a=a+0
 
 //算数运算
  print(a + b);
  print(a - b);
  print(a * b);
  print(a / b);
  print(a % b); // 取余
  print(a ~/ b); // 取整
  a ++ // 先运算再自增
  a -- //先运算再自减
  -- a // 先自减再运算
  ++ a // 先自增再运算
  
  //关系运算
  print(a == b);
  print(a >= b);
  print(a <= b);
  print(a != b);
  identical(DateTime.now(), DateTime.now()); // 判断两个对象是否相等
  
  //逻辑运算符
  || && !

类型运算符

  • as 类型转换

as运算符是一种强制类型转换,如果类型不兼容,将导致CastError。因此,在使用as时,确保您知道表达式的确切类型,并确保它与目标类型兼容

Animal animal = Dog();
Dog dog = animal as Dog;
dog.bark(); // 输出: Dog is barking
  • is 是否为某个类型,是返回true
  • is! 不是某个类型,不是返回true

条件访问与断言

  • ?[] 访问list指定位置成员,若list为空则返回null
  • ?. 访问对象指定属性或方法,若对象为空则返回null
  • a.b! 指定返回值为非null
  • ??
print(nullableString ?? 'alternate');
print(nullableString != null ? nullableString : 'alternate');
  • ??=
// Both of the following set nullableString to 'alternate' if it is null
nullableString ??= 'alternate';
nullableString = nullableString != null ? nullableString : 'alternate';

三目运算符

条件 ? 表达式 1 : 表达式 2 与其他语言类似,c此处条件必须是一个bool

级联运算符

级联运算符 (..?..) 可以让你在同一个对象上连续调用多个对象的变量或方法

var paint = Paint();
paint.color = Colors.black;
paint.strokeCap = StrokeCap.round;
paint.strokeWidth = 5.0;
 
var paint = Paint()
  ..color = Colors.black
  ..strokeCap = StrokeCap.round
  ..strokeWidth = 5.0;
-------------------------
var button = querySelector('#confirm');
button?.text = 'Confirm';
button?.classes.add('important');
button?.onClick.listen((e) => window.alert('Confirmed!'));
button?.scrollIntoView();
//使用 空判断 级联操作符 (?..)可以确保级联操作均在实例不为 null 时执行。
//使用空判断级联后,也不再需要 button 变量了:
querySelector('#confirm')
  ?..text = 'Confirm'
  ..classes.add('important')
  ..onClick.listen((e) => window.alert('Confirmed!'))
  ..scrollIntoView();

展开运算符

//你可以使用扩展操作符(...)将一个 List 中的所有元素插入到另一个 List 中:
var list = [1, 2, 3];
var list2 = [0, ...list];
assert(list2.length == 4);
 
//如果扩展操作符右边可能为 null ,你可以使用 null-aware 扩展操作符(...?)来避免产生异常:
var list2 = [0, ...?list];
assert(list2.length == 1);

判空与空安全

判空

  var str = '';
  if (str.isEmpty) {
    print(' 判断为空字符串');
  }
    var _null = null;
  if (_null == null) {
    print('判断为 null');
  }
  var _null = null;
  if (_null == null) {
    print('判断为 null');
  }

空安全

Dart 目前支持控安全机制,也就是说除非我们声明它可空,否则它们的值不能为空 声明可空的方式就是在类型前面加个问号:

  int? count;
  count = null;

如果我们知道一个值不可能为空,但是 Dart 判断可能为空,那就用!表示非空断言

  String? getData(String? data) {
    if (data is String) {
      return 'this is string data';
    }
    return null;
  }

String a = getData('12131'); //报错
String a = getData('12131')!; //正常