Design Converter
Education
Last updated on Dec 19, 2024
Last updated on Mar 6, 2024
Like many programming languages, Dart allows you to store data using variables. The value of a variable can typically be changed after it has been initialized, making it mutable. However, as a developer aiming to write efficient and maintainable code, you often need a way to ensure that the values remain constant, which is where Dart's final
and const
keywords play a crucial role.
final
and const
KeywordsWhen you declare a variable in Dart, you might decide its value should never change. This is when you reach for the final
and const
keywords, which can be used to create immutable values. But while these two keywords might seem similar at first glance, they serve different purposes, and understanding the main difference between final
and const
is crucial in writing efficient and maintainable code.
With the final
keyword, you're telling the Dart compiler that a variable can only be assigned once and its value is determined at runtime. For example:
1void main() { 2 final String greeting = 'Hello, world!'; 3 print(greeting); // Outputs: Hello, world! 4}
In this simple example, the final
variable greeting
is assigned a runtime value, a string, and cannot be changed later on.
As for the const
keyword, it takes immutability a step further. A const
variable has to be a compile-time constant, which means its value should be known at compile time. This is not only about writing maintainable code but also can improve performance since these values are determined when your code is compiled, not as it’s running. Here's how it looks in Dart:
1void main() { 2 const String exclamation = 'Welcome to Dart!'; 3 print(exclamation); // Outputs: Welcome to Dart! 4}
The const
keyword ensures that the value assigned to the exclamation
variable is a compile-time constant—it can't be changed or assigned a new value after compilation.
final
: A Closer LookWhen working with Dart, the final
keyword is your ally in creating variables that need to be assigned once and only once. A final
variable's value can be determined at runtime, which offers excellent flexibility. This allows final
variables to be initialized with data that is not known at compile time, lending itself to dynamic and responsive applications.
final
The final
keyword differs from const
because it allows for lazy initialization. This means you can assign a runtime value to a final
variable—a value determined when the code is run. For example:
1void main() { 2 final int userAge = getUserAge(); // Assume getUserAge() retrieves the user's age at runtime. 3 print(userAge); // The actual value is determined at runtime and can't be known at compile time. 4}
In this scenario, the final
variable userAge
holds a value that is assigned once at runtime and cannot be reinstantiated with a new value later in the code. Using a final
keyword instead of const
is crucial when the value to be assigned cannot be established at compile time.
final
in Class-Level VariablesAt the class level, the final
keyword helps create immutable instance variables that are initialized at the constructor level and are unique for each class instance. This aspect of final
variables plays a significant role in object-oriented programming and in creating immutable objects in Dart:
1class UserProfile { 2 final String name; 3 final DateTime accountCreationDate; 4 5 UserProfile(this.name, this.accountCreationDate); 6} 7 8void main() { 9 final user = UserProfile('Alice', DateTime.now()); 10 print(user.name); // Outputs: Alice 11 // user.name = 'Bob'; // This would result in a compile-time error. 12}
In the above class UserProfile
, name
and accountCreationDate
are final
variables. Once the UserProfile
object is created, these properties cannot be changed. Even if a new UserProfile
is instantiated, it will have its unique final
properties, providing tailored immutability at the instance level.
const
in DepthGoing beyond the final
keyword, Dart elevates immutability to a new level with the const
keyword. When you declare a const
variable, you're saying the value won't change and ensuring the variable is a compile-time constant. This means its value is determined during the compilation phase and baked into the code, which can lead to significant performance improvements.
const
const
variables in Dart are defined to be compile-time constants. The const
keyword demands that the variable's initial value be known at compile time; thus, assigning a runtime value to a const
variable is impossible. This restriction allows the Dart compiler to optimize the performance by embedding constant values directly into the code. Here's how you might use const
in a Dart program:
1void main() { 2 const int birthYear = 1990; // Known at compile time. 3 print(birthYear); // Outputs: 1990 4}
In the example above, birthYear
is a compile-time constant known at compile time and will never change. The Dart compiler understands this and can optimize accordingly.
const
VariantsDart also allows you to define literals as const
. This is particularly useful when dealing with objects like lists or maps where you want the entire data structure to be immutable:
1void main() { 2 const List<int> fibonacciNumbers = [0, 1, 1, 2, 3, 5, 8, 13]; 3 print(fibonacciNumbers); // Outputs: [0, 1, 1, 2, 3, 5, 8, 13] 4 // fibonacciNumbers[0] = 1; // This would result in a compile-time error. 5}
In the const
list fibonacciNumbers
, not only is the list itself a constant but each element is a compile-time constant too, illustrating how const
ensures deep and comprehensive immutability.
const
for Ensuring Deep ImmutabilityDeep immutability with const
goes beyond just the immediate value of a variable. Ensuring that an object is transitively immutable—meaning that all of its fields and their values are also immutable—is another powerful aspect of the const
keyword:
1class ImmutablePoint { 2 final int x; 3 final int y; 4 const ImmutablePoint(this.x, this.y); 5} 6 7void main() { 8 const ImmutablePoint origin = ImmutablePoint(0, 0); 9 print(origin.x); // Outputs: 0 10 // origin.x = 1; // This would result in a compile-time error. 11}
With the const
keyword applied to ImmutablePoint
, you guarantee that once an ImmutablePoint
object like origin
is created, it is completely immutable, including its properties x
and y
.
final
and const
The decision between final
and const
can have implications for the performance of your Dart application. The performance benefit of using const
variables comes from their nature as compile-time constants. Since const
variables are known at compile time, they are evaluated once during compilation. This means the Dart compiler can optimize them away, saving memory and reducing startup time.
1const int iterations = 1000; // A compile-time constant example.
On the other hand, final
variables are evaluated at runtime. They ensure a variable holds a single value after initialization, but this comes with the added benefit of allowing the assignment of values only known at runtime.
1final int startTime = DateTime.now().millisecondsSinceEpoch; // A runtime example.
final
Over const
and Vice Versafinal
when:
1class User { 2 final String userID; 3 User(this.userID); 4}
const
when:
1class Circle { 2 static const double pi = 3.14159; // A compile-time constant. 3}
The main difference between final
and const
can be summarized: final
is about ensuring a single value post-initialization, potentially assigned at runtime, while const
enforces immutability and constant values known at compile time.
Mastering the use of final
and const
in Dart empowers developers to write robust and efficient code. By judiciously applying final
and const
, you can avoid mutable state issues, streamline your codebase, and ensure that your Dart applications are built on a foundation of well-defined, immutable data.
Tired of manually designing screens, coding on weekends, and technical debt? Let DhiWise handle it for you!
You can build an e-commerce store, healthcare app, portfolio, blogging website, social media or admin panel right away. Use our library of 40+ pre-built free templates to create your first application using DhiWise.