Menu
Coddy logo textTech

Переменные Late

Часть раздела Объектно-ориентированное программирование путешествия по Dart на Coddy — урок 19 из 110.

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

class User {
  late String username;
  
  void initialize(String name) {
    username = name;
  }
  
  void greet() {
    print('Hello, $username!');
  }
}

User user = User();
user.initialize('Alice');
user.greet();  // Привет, Alice!

Без late Dart выдал бы ошибку, что username не инициализирована. Модификатор late обещает, что вы присвоите значение перед его чтением.

Еще одним преимуществом late является ленивая инициализация. Переменная late с инициализатором не будет вычислять свое значение до первого обращения:

class Config {
  late String settings = loadSettings();
  
  String loadSettings() {
    print('Loading...');
    return 'default';
  }
}

Config config = Config();
print('Config created');
print(config.settings);  // "Loading..." выводится здесь, затем "default"

Метод loadSettings() выполняется только при первом обращении к settings, а не при создании объекта. Однако будьте осторожны — обращение к переменной late до её инициализации вызывает ошибку времени выполнения.

challenge icon

Задание

Легко

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

Вы создадите два файла для организации вашего кода:

  • database.dart: Определите класс Database, который имитирует подключение к базе данных. Ваш класс должен иметь:
    • Переменную late String connectionString, которая будет установлена после создания объекта
    • Переменную late String status с ленивым инициализатором, который выводит Checking connection... и возвращает 'Connected'
    • Метод connect(String connStr), который устанавливает connectionString и выводит Connection configured: [connectionString]
    • Метод query(String sql), который выводит Executing on [connectionString]: [sql]
    • Метод checkStatus(), который выводит Status: [status] (это вызовет ленивую инициализацию при первом вызове)
  • main.dart: Импортируйте ваш класс базы данных и продемонстрируйте оба варианта использования late:
    • Создайте экземпляр Database
    • Выведите Database object created
    • Вызовите connect() со строкой подключения 'localhost:5432/mydb'
    • Вызовите query() с 'SELECT * FROM users'
    • Вызовите checkStatus(), чтобы запустить ленивую инициализацию

Обратите внимание, как connectionString устанавливается вручную после создания объекта, в то время как status вычисляет свое значение только при первом доступе.

Ожидаемый вывод:

Database object created
Connection configured: localhost:5432/mydb
Executing on localhost:5432/mydb: SELECT * FROM users
Checking connection...
Status: Connected

Шпаргалка

Ключевое слово late позволяет объявлять переменные, не допускающие значения null (non-nullable), которые будут инициализированы позже, перед их использованием:

class User {
  late String username;
  
  void initialize(String name) {
    username = name;
  }
}

User user = User();
user.initialize('Alice');

Ленивая инициализация: Переменная с модификатором late, имеющая инициализатор, вычисляет своё значение только при первом обращении:

class Config {
  late String settings = loadSettings();
  
  String loadSettings() {
    print('Loading...');
    return 'default';
  }
}

Config config = Config();  // loadSettings() еще не вызвана
print(config.settings);     // loadSettings() вызывается здесь

Внимание: Обращение к переменной late до её инициализации вызывает ошибку во время выполнения (runtime error).

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

import 'database.dart';

void main() {
  // TODO: Создать экземпляр Database
  
  // TODO: Вывести 'Database object created'
  
  // TODO: Вызвать connect() с 'localhost:5432/mydb'
  
  // TODO: Вызвать query() с 'SELECT * FROM users'
  
  // TODO: Вызвать checkStatus() для запуска ленивой инициализации
}
quiz iconПроверьте себя

В этом уроке есть небольшой тест. Начните урок, чтобы ответить на вопросы и сохранить прогресс.

Все уроки раздела Объектно-ориентированное программирование