Выбор ответа Middle Dart: типы и null-safety обновлено

Dart: почему не сужается тип публичного поля

Вопрос

Почему в коде ниже компилятор ругается на name.length, хотя есть проверка на null?

class Profile {
  String? name;
  void show() {
    if (name != null) {
      print(name.length); // ошибка компиляции
    }
  }
}

Попробуйте сами

Выберите вариант, и откроется разбор.

Показать ответ и разбор

Коротко

Правильный ответ: Поле может оказаться геттером или быть переопределено, второе чтение вправе вернуть null. Сужение (promotion) работает для локальных переменных и, начиная с Dart 3.2, для приватных final-полей.

Варианты ответа

  1. Поле может оказаться геттером или быть переопределено, второе чтение вправе вернуть nullправильный ответ
  2. Сужение типа в Dart работает только внутри switch и if-case, а обычный if его не даёт
  3. Нужно сравнивать через identical(name, null): оператор != не участвует в сужении типа
  4. Ошибки на самом деле нет: Dart сужает тип любых полей класса после проверки на null

Разбор

Сужение (promotion) работает для локальных переменных и, начиная с Dart 3.2, для приватных final-полей. Обычное поле может оказаться геттером или быть переопределено в подклассе, поэтому два чтения не обязаны совпадать. Решение: скопировать в локальную переменную (final n = name; if (n != null) print(n.length);). Проверка через != в if нормально участвует в сужении, дело не в ней.

Ответьте сами, а не прочитайте

В тренажёре вопрос попадёт в повторения и вернётся, когда начнёт забываться. Плюс билеты с зачётом: 20 вопросов, не больше 2 ошибок.