Published on

The Art of Being late in Dart

Authors
  • avatar
    Name
    Rosa Tiara
    Twitter

Overview

Hello again! Have you ever found yourself in a situation where you know a variable will have a value, but you can't assign it immediately? Today, we're gonna learn about the late keyword in Dart that can help with that. Let's get started!

What is it?

Think of late as telling Dart:

Hey, I promise I'll set this value before I use it, just trust me!

Just like when you tell your mom "I promise I'll do the dishes before dinner!" It's a commitment to handle something later, but importantly, you absolutely must do it.

Let's take a look at the example below:

class DishwashingSchedule {
  late bool dishesAreDone;
  
  void eveningRoutine() {
    dishesAreDone = true;
  }
}

Without late, Dart would complain that currentCity isn't initialized in the constructor. But with late, we can set it up whenever we're ready.

So, the late keyword is used to define a variable or field that will be assigned later. It allows you to declare a non-nullable variable without initializing it immediately at the time of declaration (eager initialization).

Eager initialization is not always recommended because it can limit flexibility and lead to unnecessary initialization in certain scenarios.

When should we use late?

The late keyword becomes handy in a few scenarios:

  1. When you're initializing variables that depend on something that happens after your class is created. Maybe you need to wait for some user input or an API call.
class UserProfile {
  late String username;
  
  Future<void> loadUserData() async {
    // fetching data from API, for example
    username = await fetchUsernameFromServer();
  }
}
  1. When you're dealing with dependency injection or testing. You might want to set up mock objects later:
class PaymentService {
  late PaymentProcessor processor;
  
  // service.processor = MockPaymentProcessor();
}

The Downsides of late

late isn't some magical solution to all your problems. There are a few things to watch out for:

  1. If you try to use a late variable before initializing it, your app will crash faster and throw a LateInitializationError.
void main() {
  late String name;
  print(name); // 🛑🤣 ERROR! 🛑🤣 LateInitializationError
}
  1. Using late comes with a small performance cost. Each time you access a late variable, Dart needs to check if it's been initialized.

Best Practices

✅ Here's when you should consider using late:

  • When you're absolutely damn sure the variable will be initialized before use
  • Dependency injection in testing
  • Dealing with async initialization
  • In cases where calculating an initial value is expensive and you might not need it

❌ And when you should probably avoid it:

  • When you can initialize the variable right away
  • If you're not sure whether the variable will be initialized
  • When you're just trying to avoid null safety (that's not what it's for!)

Hope this helps, happy learning!