Null-aware операторы
Часть раздела Объектно-ориентированное программирование путешествия по Dart на Coddy — урок 27 из 110.
Помимо ?. и !, Dart предоставляет дополнительные операторы, которые делают работу с nullable-значениями более лаконичной. Эти null-aware операторы помогают писать более чистый код при работе с потенциальными значениями null.
Оператор null-объединения ?? возвращает левое значение, если оно не равно null, в противном случае он возвращает правое значение:
String? nickname;
String displayName = nickname ?? 'Guest';
print(displayName); // Guest
nickname = 'Alex';
displayName = nickname ?? 'Guest';
print(displayName); // AlexОператор присваивания с проверкой на null ??= присваивает значение только в том случае, если переменная в данный момент равна null:
String? username;
username ??= 'Anonymous';
print(username); // Anonymous
username ??= 'NewName';
print(username); // По-прежнему Anonymous (не была null)Вы можете объединять в цепочку оператор доступа с проверкой на null ?. для вложенных свойств:
String? city = user?.address?.city; // Безопасно, даже если user или address равны nullЭти операторы хорошо сочетаются друг с другом. Например, вы можете обратиться к свойству, которое может принимать значение null, и указать значение по умолчанию:
String greeting = user?.name ?? 'Stranger';
// Если user равен null ИЛИ user.name равен null, использовать 'Stranger'Использование этих операторов позволяет сохранить читаемость кода, обеспечивая при этом безопасность по отношению к null во всей программе.
Задание
ЛегкоДавайте создадим систему регистрации гостей, которая продемонстрирует, как операторы с поддержкой null могут сделать ваш код чище при обработке необязательной информации.
Вы организуете свой код в двух файлах:
guest.dart: Определите классGuest, который представляет человека, посещающего мероприятие. Некоторые гости предоставляют полные данные, в то время как другие указывают только основные. Ваш класс должен содержать:- Не допускающую null строку
String name— у каждого гостя должно быть имя - Допускающую null строку
String? email— не все предоставляют адрес электронной почты - Допускающую null строку
String? dietaryPreference— некоторые гости не указывают диетические предпочтения - Конструктор, который принимает
nameкак обязательный параметр - Метод
getDisplayEmail(), который возвращает email, если он доступен, или'No email provided', используя оператор?? - Метод
assignDefaultDiet(), который устанавливаетdietaryPreferenceв значение'Standard'только в том случае, если оно в данный момент равно null, используя оператор??= - Метод
getEmailDomain(), который возвращает длину email, используя?., илиnull, если email отсутствует - Метод
printBadge(), который выводит информацию для бейджа гостя
- Не допускающую null строку
main.dart: Импортируйте ваш класс гостя и зарегистрируйте трех гостей с разным уровнем информации:- Создайте гостя по имени
'Alice', установите её email в'alice@company.com', а диетическое предпочтение — в'Vegetarian' - Создайте гостя по имени
'Bob', установите только его email в'bob@email.org'(оставьте диетическое предпочтение равным null) - Создайте гостя по имени
'Charlie'(оставьте и email, и диетическое предпочтение равными null) - Вызовите
assignDefaultDiet()для всех трех гостей - Для каждого гостя по порядку вызовите
printBadge(), затем выведитеEmail length: [result], используяgetEmailDomain()
- Создайте гостя по имени
Метод printBadge() должен выводить данные в следующем формате:
=== Guest Badge ===
Name: [name]
Email: [getDisplayEmail()]
Diet: [dietaryPreference or "Not specified"]Обратите внимание, что диетическое предпочтение Алисы остается 'Vegetarian', потому что ??= присваивает значение только тогда, когда оно равно null, в то время как Бобу и Чарли назначается диета по умолчанию 'Standard'.
Ожидаемый вывод:
=== Guest Badge ===
Name: Alice
Email: alice@company.com
Diet: Vegetarian
Email length: 17
=== Guest Badge ===
Name: Bob
Email: bob@email.org
Diet: Standard
Email length: 13
=== Guest Badge ===
Name: Charlie
Email: No email provided
Diet: Standard
Email length: nullШпаргалка
Dart предоставляет операторы с учетом null (null-aware operators) для более лаконичной работы с nullable-значениями.
Оператор объединения с null (null-coalescing operator) ?? возвращает левое значение, если оно не равно null, в противном случае возвращает правое значение:
String? nickname;
String displayName = nickname ?? 'Guest';
print(displayName); // Guest
nickname = 'Alex';
displayName = nickname ?? 'Guest';
print(displayName); // AlexОператор присваивания с учетом null (null-aware assignment operator) ??= присваивает значение только в том случае, если переменная в данный момент равна null:
String? username;
username ??= 'Anonymous';
print(username); // Anonymous
username ??= 'NewName';
print(username); // Still Anonymous (wasn't null)Вы можете объединять в цепочку оператор доступа с учетом null ?. для вложенных свойств:
String? city = user?.address?.city; // Безопасно, даже если user или address равны nullЭти операторы можно комбинировать друг с другом:
String greeting = user?.name ?? 'Stranger';
// Если user равен null ИЛИ user.name равен null, использовать 'Stranger'Попробуйте сами
import 'guest.dart';
void main() {
// TODO: Создайте гостя по имени 'Alice'
// Установите её email на 'alice@company.com'
// Установите её диетические предпочтения на 'Vegetarian'
// TODO: Создайте гостя по имени 'Bob'
// Установите только его email на 'bob@email.org'
// Оставьте диетические предпочтения как null
// TODO: Создайте гостя по имени 'Charlie'
// Оставьте и email, и диетические предпочтения как null
// TODO: Вызовите assignDefaultDiet() для всех трех гостей
// TODO: Для каждого гостя по порядку (Alice, Bob, Charlie):
// - Вызовите printBadge()
// - Выведите 'Email length: [result]', используя getEmailDomain()
}
В этом уроке есть небольшой тест. Начните урок, чтобы ответить на вопросы и сохранить прогресс.
Все уроки раздела Объектно-ориентированное программирование
1Основы ООП
Внешние файлыБиблиотеки и импортВведение в ООПКлассы и объектыКлючевое слово thisМетодыПеременные экземпляраОсновы конструкторовИтоги — Простой калькулятор4Null-безопасность
Введение в Null-безопасностьNullable и Non-Nullable типыОператоры ? и !Ключевое слово Late и Null-безопасностьNull-aware операторыNull-безопасность в классахИтоги — Система профилей пользователей7Абстрактные классы и интерфейсы
Абстрактные классыАбстрактные методыИнтерфейсы в DartНеявные интерфейсыРеализация против наследованияМножественные интерфейсыИтоги — Калькулятор фигур10Коллекции и обобщения
Обзор List, Set, MapТипобезопасные коллекцииОбобщенные классыОбобщенные методыОграничения обобщенийIterable и IteratorИтоги: Обобщенное хранилище13Продвинутые концепции ООП
Композиция против наследованияМетоды расширенияВызываемые классыЗапечатанные классы (Dart 3)Записи (Dart 3)Паттерны и сопоставление (3.0)Перечисления с методами16Проект: Управление библиотекой
Обзор проектаКлассы Book и User2Конструкторы в Dart
Конструктор по умолчаниюИменованные конструкторыСписки инициализацииКонстантные конструкторыФабричные конструкторыПеренаправляющие конструкторыИтоги — Shape Builder5Инкапсуляция
Публичные и приватные членыСоглашение о префиксе _Приватность на уровне библиотекГеттеры и сеттеры: подробный разборСкрытие данныхИтоги — Записи о студентах8Mixins
Введение в MixinsСоздание MixinsИспользование нескольких MixinsКлючевое слово on в MixinsMixin и наследованиеMixin и интерфейсИтоги: Система животных11Специальные методы
Переопределение toString()Переопределение hashCode и ==Интерфейс ComparableМетод call()Переопределение noSuchMethodПовторение — Пользовательская коллекция14Паттерны проектирования. Часть 1
Введение в паттерны проектированияПаттерн SingletonПаттерн FactoryПаттерн ObserverПаттерн Strategy3Свойства классов
Члены экземпляра и статические членыПоля Final и ConstПеременные LateСтатические методы и поляГеттеры и сеттерыИтоги — Менеджер банковского счета6Наследование
Основы наследованияКлючевое слово superПереопределение методовАннотация @overrideКлючевое слово final для классовКонструкторы и наследованиеИтоги: Иерархия сотрудников9Полиморфизм
Основы полиморфизмаПолиморфизм через интерфейсыПроверка типов во время выполненияОператоры is и asКлючевое слово covariantИтоги — Обработчик платежей12Асинхронное ООП
Futures и async/awaitОсновы StreamsКонтроллеры StreamАсинхронные конструкторыАсинхронность в методах классовИтоги — Data Fetcher15Паттерны проектирования. Часть 2
Паттерн КомандаПаттерн АдаптерПаттерн ДекораторПаттерн Шаблонный методПаттерн СостояниеПаттерн КомпоновщикПаттерн Репозиторий