什么是Dart中的Null安全性? [英] What is Null Safety in Dart?

查看:109
本文介绍了什么是Dart中的Null安全性?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我听说过新的Dart空安全语言功能(NNBD),目前是 非空实验。应该默认引入 不可为空



功能规范可以为在此处找到和语言此处的GitHub问题



它是如何工作的,我可以在哪里尝试呢?

解决方案

1。空安全性/不可为空(默认情况下)


空安全性/不可为空(默认情况下),简称NNBD,当前可在 nullsafety.dartpad.dev


请记住,您可以阅读完整规格此处此处的完整路线图。现在, Dart正式宣布。 p>



2.1。


  void main(){
字符串字;
print(word); //非法的

word =‘你好,’;
print(word); //合法
}

如上所示,变量为不可为空的默认情况下 表示正常情况下不能声明的每个变量为 null 。因此,在赋值之前访问变量的任何操作都是非法的。

此外,也不允许将 null 分配给不可空的变量:

  void main(){
字符串字;

word = null; //禁止
world =‘World!’; //允许
}


2.1.1。


如果变量是不可为空,则可以确保它永远不会为<$​​ c $ c> null 。因此,您无需事先检查。

  int number = 4; 

void main(){
if(number == null)return; //多余的

int sum =数字+ 2; //允许,因为数字也是不可为空的
}


2.1.2。请记住


中的实例字段必须初始化,如果它们不能为空:

  class Foo {
字符串字; //禁止

字符串语句=‘你好,世界!’; //允许
}

请参见下面的 late 修改此行为。


2.2。可空类型(


您可以通过添加问号<$ c $来使用可空类型 c>?转换为变量类型:

  class Foo {
字符串字; //禁止

字符串?句子; //允许
}

可空变量无需先初始化可以使用。默认情况下,它初始化为 null

  void main (){
字符串?字;

print(word); //打印null
}


2.2.2。


附加到任何变量如果 e 为null,则 e 将引发运行时错误,否则将其转换为不可为空 v

  void main(){
int? e = 5;
int v = e !; // v不可为空;如果e为空

字符串会抛出错误吗?字;
print(word!); //如果word为空,则抛出运行时错误

print(null!); //引发运行时错误
}


2.3。 late


关键字 late 可用于标记将要稍后初始化,即不是在声明它们时,而是在访问它们时。这也意味着我们可以拥有不可为空的 instance字段,这些字段稍后会初始化:

 类ExampleState扩展State {
最终String字末; //不可为空的

@override
void initState(){
super.initState();

// print(word)会引发运行时错误
word =‘Hello’;
}
}

访问单词在初始化之前,将引发运行时错误。


2.3.1。 最终最终版本


现在也可以将最终变量标记为晚了:

  late final int x = heavyComputation(); 

此处 heavyComputation 仅被调用一次 x 被访问。此外,您还可以声明 late final 而不使用初始化程序,这与只有 late 变量相同,

  late final int x;但只能分配一次。 
// w / e
x = 5; //允许
x = 6; //禁止

请注意,所有顶级静态带有初始化程序的变量现在将被评估为 late ,无论它们是否为 final


2.4。 必需


以前是注释 @必需),现在已作为修饰符内置。它允许将任何命名的参数(用于函数或类)标记为必需的,这使得它们不可为空:

 无效允许({required String word})=>空值; 

这也意味着,如果参数应不可为空,则需要对其进行标记为必需或具有默认值:

 允许无效({String word ='World'})=>空值; 

void forbidden({int x})//编译时错误,因为x可以为null(未分配)
=>
null;

任何其他命名参数必须可空


< pre class = lang-dart prettyprint-override> void baz({int?x})=>空值;


2.5。 ?[]


添加了用于感知空值的?[] 运算符索引运算符 []

  void main() {
List< int> ;?列表= [1,2,3];

int? x =清单?[0]; // 1
}

另请参见这篇关于语法决定的文章


2.5.1。 ?..


级联运算符现在还具有一个新的空感知运算符:?..


仅当收件人为不为空时,才会执行以下级联操作。因此,?.. 必须是级联序列中的第一个级联运算符:

  void main(){
路径?路径;

//如果path为null,则不执行任何操作。
path
?.. moveTo(3,4)
..lineTo(4,3);

//这是一个小问题。
(null为List)
?.. add(4)
..add(2)
..add(0);
}




2.6。 从不


为避免混淆:开发人员不必担心这一点。为了完整起见,我想提及它。


从不会像以前的 Null 不是在 dart:core 中定义的 null )。这两个类都不能扩展,实现或混合使用,因此不打算使用它们。


本质上,从不表示不允许使用任何类型,并且从不本身不能被实例化。

除了从不 List< Never> 中的列表满足列表的通用类型约束,这意味着它必须为空 List< Null> ,但是可以包含 null

  //唯一有效的状态:[] 
final neverList =< Never> [
//任何值,但从不出现错误。
5,//错误
null,//错误

从不,//不是一个值(编译时错误)
];

//可以包含null:[null]
final nullList =< Null> [
//除Null之外的任何值都是错误。
5,//错误
null,//允许

从不,//不是值(编译时错误)
Null,//不是值(编译时错误)
];

示例:编译器将推断 List< Never> 常量列表< T>

从不是就我而言,程序员不应该使用它。


3。了解更多信息


您可以阅读有关声音无效安全性的官方文章

此外,如开头所述,您可以在DartPad上玩


I have heard of the new Dart null safety language feature (NNBD), currently the "'non-nullable' experiment". It is supposed to introduce non-nullable by default.

The feature specification can be found here and the language GitHub issue here.

How does it work and where can I try it?

解决方案

1. Null safety / non-nullable (by default)

The null safety / non-nullable (by default), short NNBD, feature can currently be found at nullsafety.dartpad.dev.

Keep in mind that you can read the full spec here and full roadmap here. Now, sound null safety has also been officially announced for Dart.


2.1. What does non-nullable by default mean?

void main() {
  String word;
  print(word); // illegal

  word = 'Hello, ';
  print(word); // legal
}

As you can see above, a variable being non-nullable by default means that every variable that is declared normally cannot be null. Consequently, any operation accessing the variable before it has been assigned is illegal.
Additionally, assigning null to a non-nullable variable is also not allowed:

void main() {
  String word;
  
  word = null; // forbidden
  world = 'World!'; // allowed
}

2.1.1. How does this help me?

If a variable is non-nullable, you can be sure that it is never null. Because of that, you never need to check it beforehand.

int number = 4;

void main() {
  if (number == null) return; // redundant

  int sum = number + 2; // allowed because number is also non-nullable
}

2.1.2. Remember

Instance fields in classes must be initialized if they are not nullable:

class Foo {
  String word; // forbidden

  String sentence = 'Hello, World!'; // allowed
}

See late below to modify this behavior.

2.2. Nullable types (?)

You can use nullable types by appending a question mark ? to a variable type:

class Foo {
  String word; // forbidden

  String? sentence; // allowed
}

A nullable variable does not need to be initialized before it can be used. It is initialized as null by default:

void main() {
  String? word;
  
  print(word); // prints null
}

2.2.2. !

Appending ! to any variable e will throw a runtime error if e is null and otherwise convert it to a non-nullable value 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
}

2.3. late

The keyword late can be used to mark variables that will be initialized later, i.e. not when they are declared but when they are accessed. This also means that we can have non-nullable instance fields that are initialized later:

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';
  }
}

Accessing word before it is initialized will throw a runtime error.

2.3.1. late final

Final variables can now also be marked late:

late final int x = heavyComputation();

Here heavyComputation will only be called once x is accessed. Additionally, you can also declare a late final without an initializer, which is the same as having just a late variable, but it can only be assigned once.

late final int x;
// w/e
x = 5; // allowed
x = 6; // forbidden

Note that all top-level or static variables with an initializer will now be evaluated late, no matter if they are final.

2.4. required

Formerly an annotation (@required), now built-in as a modifier. It allows to mark any named parameter (for functions or classes) as required, which makes them non-nullable:

void allowed({required String word}) => null;

This also means that if a parameter should be non-nullable, it needs to be marked as required or have a default value:

void allowed({String word = 'World'}) => null;

void forbidden({int x}) // compile-time error because x can be null (unassigned)
    =>
    null;

Any other named parameter has to be nullable:

void baz({int? x}) => null;

2.5. ?[]

The null aware ?[] operator was added for the index operator []:

void main() {
  List<int>? list = [1, 2, 3];

  int? x = list?[0]; // 1
}

See also this article about the syntax decision.

2.5.1. ?..

The cascade operator now also has a new null aware operator: ?...

It causes the following cascade operations to only be executed if the recipient is not null. Therefore, the ?.. has to be the first cascade operator in a cascade sequence:

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);
}


2.6. Never

To avoid confusion: this is not something that developers have to worry about. I want to mention it for the sake of completeness.

Never is going to be a type like the previously existing Null (not null) defined in dart:core. Both of these classes cannot be extended, implemented, or mixed in, so they are not intended to be used.

Essentially, Never means that no type is allowed and Never itself cannot be instantiated.
Nothing but Never in a List<Never> satisfies the generic type constraint of the list, which means that it has to be empty. List<Null>, however, can contain 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)
];

Example: the compiler will infer List<Never> for an empty const List<T>.
Never is not supposed to be used by programmers as far as I am concerned.

3. Learn more

You can read the official article on sound null safety.
Furthermore as mentioned at the beginning, you can play with it on DartPad.

这篇关于什么是Dart中的Null安全性?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆