Null-Aware Operators
Part of the Object Oriented Programming section of Coddy's Dart journey — lesson 27 of 110.
Beyond ?. and !, Dart provides additional operators that make working with nullable values more concise. These null-aware operators help you write cleaner code when dealing with potential null values.
The null-coalescing operator ?? returns the left value if it's not null, otherwise it returns the right value:
String? nickname;
String displayName = nickname ?? 'Guest';
print(displayName); // Guest
nickname = 'Alex';
displayName = nickname ?? 'Guest';
print(displayName); // AlexThe null-aware assignment operator ??= assigns a value only if the variable is currently null:
String? username;
username ??= 'Anonymous';
print(username); // Anonymous
username ??= 'NewName';
print(username); // Still Anonymous (wasn't null)You can chain the null-aware access operator ?. for nested properties:
String? city = user?.address?.city; // Safe even if user or address is nullThese operators combine well together. For example, you might access a nullable property and provide a default:
String greeting = user?.name ?? 'Stranger';
// If user is null OR user.name is null, use 'Stranger'Using these operators keeps your code readable while maintaining null safety throughout your program.
Challenge
EasyLet's build a guest registration system that demonstrates how null-aware operators can make your code cleaner when handling optional information.
You'll organize your code into two files:
guest.dart: Define aGuestclass that represents someone attending an event. Some guests provide full details, while others only give the basics. Your class should have:- A non-nullable
String name- every guest must have a name - A nullable
String? email- not everyone provides an email - A nullable
String? dietaryPreference- some guests don't specify dietary needs - A constructor that takes
nameas a required parameter - A method
getDisplayEmail()that returns the email if available, or'No email provided'using the??operator - A method
assignDefaultDiet()that setsdietaryPreferenceto'Standard'only if it's currently null, using the??=operator - A method
getEmailDomain()that returns the length of the email using?., ornullif no email exists - A method
printBadge()that prints the guest's badge information
- A non-nullable
main.dart: Import your guest class and register three guests with varying levels of information:- Create a guest named
'Alice', set her email to'alice@company.com'and dietary preference to'Vegetarian' - Create a guest named
'Bob', set only his email to'bob@email.org'(leave dietary preference as null) - Create a guest named
'Charlie'(leave both email and dietary preference as null) - Call
assignDefaultDiet()on all three guests - For each guest in order, call
printBadge(), then printEmail length: [result]usinggetEmailDomain()
- Create a guest named
The printBadge() method should print in this format:
=== Guest Badge ===
Name: [name]
Email: [getDisplayEmail()]
Diet: [dietaryPreference or "Not specified"]Notice how Alice's dietary preference stays 'Vegetarian' because ??= only assigns when the value is null, while Bob and Charlie get the default 'Standard' diet assigned.
Expected output:
=== 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: nullCheat sheet
Dart provides null-aware operators to work with nullable values more concisely.
The null-coalescing operator ?? returns the left value if it's not null, otherwise returns the right value:
String? nickname;
String displayName = nickname ?? 'Guest';
print(displayName); // Guest
nickname = 'Alex';
displayName = nickname ?? 'Guest';
print(displayName); // AlexThe null-aware assignment operator ??= assigns a value only if the variable is currently null:
String? username;
username ??= 'Anonymous';
print(username); // Anonymous
username ??= 'NewName';
print(username); // Still Anonymous (wasn't null)You can chain the null-aware access operator ?. for nested properties:
String? city = user?.address?.city; // Safe even if user or address is nullThese operators can be combined together:
String greeting = user?.name ?? 'Stranger';
// If user is null OR user.name is null, use 'Stranger'Try it yourself
import 'guest.dart';
void main() {
// TODO: Create a guest named 'Alice'
// Set her email to 'alice@company.com'
// Set her dietary preference to 'Vegetarian'
// TODO: Create a guest named 'Bob'
// Set only his email to 'bob@email.org'
// Leave dietary preference as null
// TODO: Create a guest named 'Charlie'
// Leave both email and dietary preference as null
// TODO: Call assignDefaultDiet() on all three guests
// TODO: For each guest in order (Alice, Bob, Charlie):
// - Call printBadge()
// - Print 'Email length: [result]' using getEmailDomain()
}
This lesson includes a short quiz. Start the lesson to answer it and track your progress.
All lessons in Object Oriented Programming
1Fundamentals of OOP
External FilesLibraries & ImportsIntroduction to OOPClasses vs ObjectsThe this KeywordMethodsInstance VariablesConstructor BasicsRecap - Simple Calculator4Null Safety
Intro to Null SafetyNullable vs Non-NullableThe ? and ! OperatorsLate Keyword & Null SafetyNull-Aware OperatorsNull Safety in ClassesRecap - User Profile System7Abstract Classes & Interfaces
Abstract ClassesAbstract MethodsInterfaces in DartImplicit InterfacesImplementing vs ExtendingMultiple InterfacesRecap - Shape Calculator10Collections & Generics
List, Set, Map OverviewType-Safe CollectionsGeneric ClassesGeneric MethodsGeneric ConstraintsIterable & IteratorRecap - Generic Storage13Advanced OOP Concepts
Composition vs InheritanceExtension MethodsCallable ClassesSealed Classes (Dart 3)Records (Dart 3)Patterns & Matching (3.0)Enums with Methods16Project: Library Management
Project OverviewBook and User Classes2Constructors in Dart
Default ConstructorNamed ConstructorsInitializer ListsConstant ConstructorsFactory ConstructorsRedirecting ConstructorsRecap - Shape Builder5Encapsulation
Public vs Private MembersThe _ Prefix ConventionLibrary-Level PrivacyGetters & Setters DepthInformation HidingRecap - Student Records8Mixins
Introduction to MixinsCreating MixinsUsing Multiple Mixinson Keyword in MixinsMixin vs InheritanceMixin vs InterfaceRecap - Animal System11Special Methods
toString() OverridehashCode & == OverrideComparable Interfacecall() MethodnoSuchMethod OverrideRecap - Custom Collection14Design Patterns Part 1
Intro to Design PatternsSingleton PatternFactory PatternObserver PatternStrategy Pattern3Class Properties
Instance vs Static MembersFinal & Const FieldsLate VariablesStatic Methods & FieldsGetters and SettersRecap - Bank Account Manager6Inheritance
Basic InheritanceThe super KeywordMethod OverridingThe @override AnnotationThe final Class KeywordConstructors & InheritanceRecap - Employee Hierarchy9Polymorphism
Polymorphism BasicsPolymorphism via InterfacesRuntime Type CheckingThe is & as OperatorsCovariant KeywordRecap - Payment Processor