我已将DART代码迁移到NNBD/Null Safety.其中一些看起来像这样:

class Foo {
  String? _a;
  void foo() {
    if (_a != null) {
      _a += 'a';
    }
  }
}

class Bar {
  Bar() {
    _a = 'a';
  }
  String _a;
}

这会导致两个分析错误._a += 'a';美元:

值可以为‘null’must be null-checked的表达式,然后才能取消引用. 在取消引用该值之前,请try 判断该值是否不为"null".

对于Bar() {:

必须初始化不可为空的实例字段‘_a’. try 添加初始值设定项表达式or add a field initializer in this constructor,或将其标记为"Late".

在这两种情况下,我已经完全按照错误的建议执行了操作!那是怎么回事?

我用的是dart 2.12.0-133.2.beta(12月15日星期二).

编辑:我找到了this page个,上面写着:

分析器不能对整个应用程序的流进行建模,因此它不能预测全局变量或类字段的值.

但这对我来说没有意义-在本例中,从if (_a != null)_a += 'a';只有一条可能的流控制路径-没有异步代码,并且DART是单线程的-所以_a不是本地的也没有关系.

Bar()的错误消息明确说明了在构造函数中初始化字段的可能性.

推荐答案

问题是,即使类字段被标记为final,它也可以被重写.以下示例说明了该问题:

class A {
  final String? text = 'hello';

  String? getText() {
    if (text != null) {
      return text;
    } else {
      return 'WAS NULL!';
    }
  }
}

class B extends A {
  bool first = true;

  @override
  String? get text {
    if (first) {
      first = false;
      return 'world';
    } else {
      return null;
    }
  }
}

void main() {
  print(A().getText()); // hello
  print(B().getText()); // null
}

B类重写text final字段,因此它在第一次被询问时返回一个值,但在此之后返回null.编写A类的方式不能阻止这种形式的重写被允许.

因此,我们无法将getText的返回值从String?更改为String,即使看起来我们在返回之前判断了text字段中的null.

Dart相关问答推荐

将所有内容放在有序组中,但将括号中的字符组合在一起

播放和暂停 Flutter 动画

如何防止多行文本小部件放置在行中时被剪裁?

如何等待forEach完成异步回调?

如何在Flatter中更改复选框边框 colored颜色 ?默认情况下,它显示为黑色,但我希望它显示为灰色

使用 Dart 计算字符串中字母的数量

Flutter-键盘显示和隐藏导致生成调用

Flutter SlideTransition 从 Offset OFF SCREEN 开始

Flatter BLoC-如何将参数传递给事件?

在 TextInputType 更改后控制器重置的 Flutter TextField

你如何在 Dart 中将月份的日期格式化为11th、21st或23rd?

Flutter - 在 POST 请求中处理状态码 302

Flutter: shared preferences

有没有更好的方法来找出文件或目录是否存在?

如何在 Dart 中创建我们自己的metadata元数据?

如何在 Dart 2 中将 List 更改为 List

以编程方式使dart中的十六进制 colored颜色 变亮或变暗

如何重新引发异常并保留堆栈跟踪?

如何将 `ByteData` 实例写入 Dart 中的文件?

将`_`(即下划线)作为唯一参数传递给 Dart 语言函数是什么意思?