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: nullTry 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 ProcessorPractice on your own: Online Dart compiler