我听说过新的Dart空安全语言功能(NNBD),目前是“ “不可空”实验”。应该默认引入 不可为空 。
功能规范可以为found here和语言为GitHub issue here。
它如何工作?在哪里可以尝试?
答案 0 :(得分:84)
当前可以在nullsafety.dartpad.dev上找到空安全性/不可空性(默认情况下),简短的NNBD功能。
请记住,您可以阅读full spec here和full roadmap here。现在,声音无效的安全性也已经officially announced for Dart。
void main() {
String word;
print(word); // illegal
word = 'Hello, ';
print(word); // legal
}
如上所述,变量默认为不可为空 ,这意味着通常不能声明的每个变量均为{{ 1}}。因此,在赋值之前访问变量的任何操作都是非法的。
此外,也不允许将null
分配给不可为空的变量:
null
如果变量不可为空,则可以确保它永远不会void main() {
String word;
word = null; // forbidden
world = 'World!'; // allowed
}
。因此,您无需事先检查。
null
类中的实例字段不可为空,则必须对其进行初始化:
int number = 4;
void main() {
if (number == null) return; // redundant
int sum = number + 2; // allowed because number is also non-nullable
}
请参见下面的class Foo {
String word; // forbidden
String sentence = 'Hello, World!'; // allowed
}
来修改此行为。
late
)您可以通过将问号?
附加到变量类型来使用可空类型:
?
可空变量无需初始化即可使用。默认情况下,它初始化为class Foo {
String word; // forbidden
String? sentence; // allowed
}
:
null
void main() {
String? word;
print(word); // prints null
}
如果将!
为null,则将 !
附加到任何变量e
会引发运行时错误,否则会将其转换为不可为空值e
。
v
void main() {
int? e = 5;
int v = e!; // v is non-nullable; would throw an error if e were null
String? word;
print(word!); // throws runtime error if word is null
print(null!); // throws runtime error
}
关键字late
可用于标记稍后将初始化的变量,即不是在声明它们时而是在访问它们时。这也意味着我们可以拥有不可空的 instance字段,这些字段稍后会初始化:
late
在初始化之前访问class ExampleState extends State {
late final String word; // non-nullable
@override
void initState() {
super.initState();
// print(word) here would throw a runtime error
word = 'Hello';
}
}
会引发运行时错误。
word
现在也可以将最终变量标记为更晚了:
late final
这里late final int x = heavyComputation();
仅在访问heavyComputation
后才被调用。另外,您也可以声明一个没有初始化程序的x
,这与只有一个late final
变量的情况相同,但是只能分配一次。
late
请注意,带有初始化程序的所有顶级或 static 变量现在都将被late final int x;
// w/e
x = 5; // allowed
x = 6; // forbidden
求值,无论它们是late
。
final
以前是注释(required
),现在已作为修饰符内置。它允许将任何命名参数(对于函数或类)标记为@required
,这使它们不可为空:
required
这还意味着,如果参数应不可为空,则需要将其标记为void allowed({required String word}) => null;
或具有默认值:
required
任何其他命名参数都必须可空:
void allowed({String word = 'World'}) => null;
void forbidden({int x}) // compile-time error because x can be null (unassigned)
=>
null;
void baz({int? x}) => null;
为索引运算符?[]
添加了空感知的?[]
运算符:
[]
另请参阅this article about the syntax decision。
void main() {
List<int>? list = [1, 2, 3];
int? x = list?[0]; // 1
}
级联运算符现在还具有一个新的空感知运算符:?..
。
仅当收件人为不为空时,才会执行以下级联操作。因此,?..
必须是级联序列中的第一个级联运算符:
?..
void main() {
Path? path;
// Will not do anything if path is null.
path
?..moveTo(3, 4)
..lineTo(4, 3);
// This is a noop.
(null as List)
?..add(4)
..add(2)
..add(0);
}
以下解释很糟糕。阅读"Top and bottom" from "Understanding null safety" 读一本书。
为避免混淆:开发人员不必担心这一点。为了完整起见,我想提一下。
Never
的类型将类似于Never
中定义的先前存在的Null
(不是null
)。这两个类都不能扩展,实现或混合,因此不打算使用它们。
本质上,dart:core
表示不允许任何类型,Never
本身无法实例化。
Never
中的Never
都不满足列表的通用类型约束,这意味着它必须为空 。 List<Never>
但是可以包含List<Null>
:
null
示例:编译器将推断// Only valid state: []
final neverList = <Never>[
// Any value but Never here will be an error.
5, // error
null, // error
Never, // not a value (compile-time error)
];
// Can contain null: [null]
final nullList = <Null>[
// Any value but Null will be an error.
5, // error
null, // allowed
Never, // not a value (compile-time error)
Null, // not a value (compile-time error)
];
为空 List<Never>
。
就我而言,const List<T>
不应由程序员使用。 (I was wrong)。
您可以阅读official article on sound null safety。
此外,如开头所述,您可以play with it on DartPad。
答案 1 :(得分:-3)
如果您希望此字段为必填项,则使用必填关键字,否则您只需输入“?”。像这样
const phonefield({
Key? key,required this.onchanged,
}) : super(key: key);
final ValueChanged<String>onchanged;