Что такое нулевая безопасность в Dart?

Я слышал о новой функции языка безопасности с нулевым значением Dart (NNBD), которая в настоящее время является " экспериментом, не допускающим значения NULL ". По умолчанию предполагается ввести значение, не допускающее значения NULL.

Спецификацию функции можно найти здесь, а вопрос о языке GitHub здесь.

Как это работает и где я могу это попробовать?

2 ответа

Решение

1. Безопасность с нулевым значением / не допускающее значение NULL (по умолчанию)

Нулевую безопасность / не допускающую обнуление (по умолчанию), короткую функцию NNBD, в настоящее время можно найти по адресу https://nullsafety.dartpad.dev/.

Имейте в виду, что вы можете прочитать полную спецификацию здесь и полную дорожную карту здесь. Теперь для Dart официально объявлено о нулевой безопасности звука.


2.1. Что означает значение по умолчанию, не допускающее значения NULL?

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

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

Как вы можете видеть выше, переменная, не допускающая значения NULL по умолчанию, означает, что каждая переменная, которая обычно объявлена, не может бытьnull. Следовательно, любая операция доступа к переменной до того, как она была назначена, является незаконной.
Дополнительно присвоениеnull в переменную, не допускающую значения NULL, также не допускается:

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

2.1.1. Как это мне помогает?

Если переменная не допускает значения NULL, вы можете быть уверены, что она никогда не будетnull. Благодаря этому вам никогда не нужно проверять его заранее.

int number = 4;

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

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

2.1.2. Помнить

Поля экземпляра в классах должны быть инициализированы, если они не допускают значения NULL:

class Foo {
  String word; // forbidden

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

Увидеть late ниже, чтобы изменить это поведение.

2.2. Обнуляемые типы (?)

Вы можете использовать типы, допускающие значение NULL, добавив вопросительный знак? к типу переменной:

class Foo {
  String word; // forbidden

  String? sentence; // allowed
}

Обнуляемым переменная не должна быть инициализирована, прежде чем он может быть использован. Он инициализируется какnull по умолчанию:

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

2.2.2. !

Добавление ! к любой переменной eвыдаст ошибку времени выполнения, еслиeимеет значение NULL, и в противном случае преобразовать его в значение, не допускающее значения NULLv.

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

Ключевое слово lateможет использоваться для обозначения переменных, которые будут инициализированы позже, то есть не при их объявлении, а при обращении к ним. Это также означает, что у нас могут быть поля экземпляра, не допускающие значения NULL, которые инициализируются позже:

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 перед его инициализацией вызовет ошибку времени выполнения.

2.3.1. late final

Конечные переменные теперь также могут быть отмечены поздно:

late final int x = heavyComputation();

Вот heavyComputation будет вызван только один раз xдоступен. Кроме того, вы также можете объявитьlate final без инициализатора, что равносильно наличию late переменная, но ее можно присвоить только один раз.

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

Обратите внимание, что теперь будут оцениваться все статические переменные или переменные верхнего уровня с инициализатором.late, неважно, если они final.

2.4. required

Ранее аннотация (@required), теперь встроенный как модификатор. Это позволяет пометить любой именованный параметр (для функций или классов) какrequired, что делает их не допускающими значения NULL:

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

Это также означает, что если параметр не должен допускать значения NULL, его необходимо пометить какrequired или иметь значение по умолчанию:

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

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

Любой другой именованный параметр должен иметь значение NULL:

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

2.5. ?[]

Нулевой осведомленный ?[] добавлен оператор индексации []:

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

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

См. Также эту статью о решении синтаксиса.

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

2.6. 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>.
Never Насколько я понимаю, программисты не должны использовать его.

3. Узнать больше

Вы можете прочитать официальную статью о нулевой безопасности звука.
Кроме того, как упоминалось в начале, вы можете играть с ним на DartPad.

если вы хотите, чтобы это поле было обязательным, используйте обязательное ключевое слово, в противном случае вам нужно только поставить «?». как это

      const phonefield({
    Key? key,required this.onchanged,

  }) : super(key: key);
  final  ValueChanged<String>onchanged;
Другие вопросы по тегам