我已经将我的项目升级为null-safety,这有点令人困惑,因为如果我包装成
if(someObject.field != null) {
doSomething(someObject.field); // error, can't assign String? to String
}
需要非空属性的方法调用,并且我试图传递的变量是空的,然后我得到一个类型错误,我不能将可空值赋给非空类型。
但是当我做的时候
String? someObjectField = someObject!.field;
if(someObjectField != null) {
doSometing(someObjectField); // Can assign
}
运行正常
doSomething = (String foo) {}
例如:
class Person {
final String name;
Person(this.name);
}
Function test = () {
Map<String, String?> pers = {
'name': 'John',
};
if(pers['name'] != null) {
Person(pers['name']); // Error, even if it will be never executed
Person(pers['name'] as String); // no error
Person(pers['name']!); // no error
}
};
如果我这样做:
if (widget.event != null && widget.event.featuredImage != null)
然后它在第二个语句中抱怨接收器(widget.event)可以为空,我需要使用!
,但第二个语句不应该执行,它不应该导致运行时异常。
所以我需要把它修改为:
if (widget.event != null && widget.event!.featuredImage != null)
但是当我尝试在Flutter中使用嵌套小部件时,即使我使用if
作为包装器,我仍然需要在任何地方添加!
Stack(
children: [
// Add Container with image only when event and futured image are not null
if (widget.event != null && widget.event!.featuredImage != null) ...[
Container(
height: 250,
decoration: BoxDecoration(
color: Colors.transparent,
image: DecorationImage(
fit: BoxFit.cover,
image: NetworkImage(widget.event!.featuredImage!), // here i Need to use ! to satisfy the compiler
),
),
),
],
],
)
或者,我可以将变量提取到另一个String? image = widget.event!.featuredImage
中,然后将if
语句修改为if(image != null)
,并使用像NetworkImage(image)
这样的小部件,它按预期工作。
与TypeScript相比,它会检测我是否在上面的条件中检查了null,这对我来说毫无意义。
长话短说,即使我检查null值渲染/不渲染组件,我仍然需要使用!
。
有什么明显的我错过了吗?
提前谢谢你
既然你把它和TypeScript比较了,是的,你错过了一些东西。
Typescript是一团乱麻,只能在非常有限的环境中工作,而且"works"被严重夸大了。例如,你可以在typescript中写一个功能它接受一个字符串,然后在运行时发现它实际上不是一个字符串,很意外,它是一个完全不同的类型。JavaScript的乐趣。调用TypeScript "type safe"与JS相比是正确的,与实际编译语言相比是荒谬的。
因此,您错过了Dart编译器可以保证一旦您检查它,它就不为空的事实。要做到这一点,它需要额外的约束。例如,可以让getter在每次调用时都返回不同的值。例如,根据getter的代码,您的调用在第一次和第二次调用之间很容易返回不同的值。或者您可以使用继承和多态性来构建一些更有问题的结构。这里有一个有趣的例子。因此,您需要有一个局部变量,保证具有相同的值,除非显式更改。
您的if (widget.event != null && widget.event.featuredImage != null)
示例可以很容易地修改为:
final image = widget?.event?.featuredImage;
Stack(
children: [
// Add Container with image only when event and futured image are not null
if (image != null) ...[
Container(
height: 250,
decoration: BoxDecoration(
color: Colors.transparent,
image: DecorationImage(
fit: BoxFit.cover,
image: NetworkImage(image),
),
),
),
],
],
)
是的,你必须实现一些微小的逻辑,你不能只是把?
和!
放在你的代码上,它就像以前一样运行。但一旦你理解了逻辑上的小变化是什么,就很容易了。