Что такое ключевое слово ‘late’ в Dart?

«Что такое ключевое слово ‘late’ в Dart?» — вопрос из категории Dart Core, который задают на 29% собеседований Flutter Разработчик. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

Ключевое слово late в Dart используется для объявления переменной, инициализация которой будет отложена до момента её первого использования. Оно даёт компилятору гарантию, что к моменту чтения переменная будет проинициализирована, что позволяет использовать non-nullable типы (String, int, CustomClass) там, где значение неизвестно сразу.

Основные причины использования late:

  1. Отложенная инициализация в конструкторе: Когда значение зависит от вычислений или аргументов, которые становятся известны внутри конструктора, но не могут быть переданы как параметры инициализатора.
  2. Инициализация в методе initState: Для полей в StatefulWidget, которые настраиваются при инициализации виджета.
  3. Ленивая инициализация (lazy): Когда переменная инициализируется только при первом обращении к ней, что может быть полезно для тяжеловесных объектов.

Пример 1: Отложенная инициализация

class WeatherService {
  late final String _apiKey; // Не инициализирована сразу

  WeatherService() {
    // Ключ получаем асинхронно или из сложной логики
    _apiKey = _fetchApiKeyFromConfig();
  }

  String _fetchApiKeyFromConfig() => 'some_key';
}

Пример 2: Ленивая инициализация (вычисляется один раз при первом обращении)

class ExpensiveObject {
  late final HeavyClass _heavyInstance = HeavyClass();
  // _heavyInstance будет создан только при первом вызове getter'а
}

Важное предупреждение: Если прочитать late-переменную до её инициализации, будет выброшено исключение LateInitializationError. Это делает код безопаснее, чем использование nullable-типа (String?), так как ошибка обнаруживается сразу в рантайме, а не приводит к скрытым null.