In Dart, final and const are two keywords that are used to declare variables whose values cannot be changed after they are initially set. While they seem similar, they are used in different contexts and have distinct behaviors.
A final variable is a variable whose value can be assigned only once. Once a value is assigned to a final variable, it cannot be changed.
final variables are evaluated at runtime and are immutable after initialization.
final variables can be initialized with a value computed at runtime (like the result of a function call or user input).
Key Characteristics of final:
A final variable must be initialized only once.
It can be initialized at runtime, but only once.
It is not a compile-time constant—its value is determined at runtime.
Example of final:
dart
Copy code
void main() {
final String name = 'Alice'; // Initializing a final variable with a string
print(name); // Prints: Alice
// Uncommenting the following line will result in an error, because 'name' is final
// name = 'Bob'; // Error: Cannot assign to the final variable 'name'
}
In the above example, name is a final variable, and its value cannot be reassigned after the first assignment. However, the value of name is determined at runtime and can be assigned dynamically based on calculations, input, or logic.
A const variable is a compile-time constant, meaning its value is determined at compile time and cannot change during runtime.
The const keyword can be used for both variables and collections (like lists and maps) to create constant values that are fixed and known before the program runs.
const values must be assigned at compile time, and the value of a const variable is set before the program starts executing.
Key Characteristics of const:
Compile-time constant: The value of a const variable is computed at compile time.
Cannot be assigned a value that is determined at runtime (e.g., the result of a function call).
Can be used to create constant objects, including collections like List and Map.
Example of const:
dart
Copy code
void main() {
const String country = 'USA'; // Initializing a const variable with a string
print(country); // Prints: USA
// Uncommenting the following line will result in an error, because 'country' is const
// country = 'Canada'; // Error: Can't assign to the const variable 'country'
}
In this example, the value of country is a compile-time constant. It is evaluated during the compilation of the program, meaning no runtime calculation or assignment can occur. The value is strictly fixed at compile time.
Evaluation Time:
final: The value is assigned and evaluated at runtime.
const: The value is assigned and evaluated at compile-time.
Reassignability:
final: The variable can only be assigned once, but it can be assigned a value computed during runtime.
const: The variable must have a compile-time constant value and cannot be reassigned.
Use Cases:
final: Useful when you want to assign a value once, but the value is computed at runtime, such as from user input or calculations.
const: Useful when you want the value to be constant and known before the program runs, such as configuration values or static constants.
final with a runtime value:
dart
Copy code
void main() {
final DateTime currentDate = DateTime.now(); // Using `final` with a runtime value
print('Current Date: $currentDate'); // Prints the current date/time
// You cannot reassign `final` variables
// Uncommenting the line below will result in an error
// currentDate = DateTime(2023, 1, 1); // Error: Cannot assign to the final variable 'currentDate'
}
In this example, currentDate is a final variable because it is assigned a value that is determined at runtime, which is the current date and time.
const with a compile-time value:
dart
Copy code
void main() {
const double pi = 3.14159; // Using `const` with a compile-time value
print('Value of Pi: $pi'); // Prints: Value of Pi: 3.14159
// You cannot reassign `const` variables
// Uncommenting the line below will result in an error
// pi = 3.14; // Error: Constant variables can't be assigned a value.
}
In this example, pi is a const variable because its value is a compile-time constant, known before the program is executed.
const with Collections:
dart
Copy code
void main() {
const List<int> numbers = [1, 2, 3]; // Declaring a constant list
print(numbers); // Prints: [1, 2, 3]
// Uncommenting the following line will result in an error because `numbers` is a const list
// numbers[0] = 10; // Error: Cannot modify an unmodifiable list
}
In this example, the numbers list is declared as const, making the entire list immutable, both in terms of the list itself and its contents. The contents of a const list cannot be modified.
Use final when:
You need a variable whose value will not change after being set, but that value is determined at runtime.
You want to assign a value that is computed, fetched from an API, or comes from user input.
Use const when:
You need a compile-time constant, like a value that will never change (e.g., mathematical constants, static values).
You want to create constant objects or collections that are evaluated at compile-time.
dart
Copy code
void main() {
final int age = 25; // Declaring a final variable
print('Age: $age'); // Prints: Age: 25
// Uncommenting the following line will result in an error
// age = 30; // Error: Cannot assign to the final variable 'age'
}
dart
Copy code
void main() {
final String name = 'John'; // Declaring a final string variable
print('Name: $name'); // Prints: Name: John
// Uncommenting the following line will result in an error
// name = 'Jane'; // Error: Cannot assign to the final variable 'name'
}
dart
Copy code
void main() {
const double pi = 3.14159; // Declaring a const variable
print('Pi: $pi'); // Prints: Pi: 3.14159
// Uncommenting the following line will result in an error
// pi = 3.14; // Error: Constant variables can't be assigned a value.
}
dart
Copy code
int getRandomNumber() {
return 42; // Return a random number (static for this example)
}
void main() {
final int randomNum = getRandomNumber(); // Final variable assigned at runtime
print('Random Number: $randomNum'); // Prints: Random Number: 42
// Uncommenting the following line will result in an error
// randomNum = 50; // Error: Cannot assign to the final variable 'randomNum'
}
dart
Copy code
void main() {
final List<String> fruits = ['Apple', 'Banana', 'Cherry']; // Final list
print('Fruits: $fruits'); // Prints: Fruits: [Apple, Banana, Cherry]
fruits.add('Mango'); // Allowed: You can modify the contents of a final list
print('Updated Fruits: $fruits'); // Prints: Updated Fruits: [Apple, Banana, Cherry, Mango]
// You can't reassign the list itself
// Uncommenting the following line will result in an error
// fruits = ['Orange', 'Grapes']; // Error: Cannot assign to the final variable 'fruits'
}
dart
Copy code
void main() {
const List<String> colors = ['Red', 'Green', 'Blue']; // Declaring a const list
print('Colors: $colors'); // Prints: Colors: [Red, Green, Blue]
// Uncommenting the following line will result in an error
// colors.add('Yellow'); // Error: Cannot modify an unmodifiable list
// You cannot reassign a const list either
// Uncommenting the following line will result in an error
// colors = ['Black', 'White']; // Error: Can't assign to the const variable 'colors'
}
dart
Copy code
void main() {
const Map<String, String> countryCapital = {
'USA': 'Washington, D.C.',
'France': 'Paris',
'India': 'New Delhi'
}; // Declaring a const map
print('Country and Capital: $countryCapital');
// Prints: Country and Capital: {USA: Washington, D.C., France: Paris, India: New Delhi}
// Uncommenting the following line will result in an error
// countryCapital['Canada'] = 'Ottawa'; // Error: Cannot modify an unmodifiable map
// You cannot reassign a const map either
// Uncommenting the following line will result in an error
// countryCapital = {'Germany': 'Berlin'}; // Error: Can't assign to the const variable 'countryCapital'
}
dart
Copy code
class Car {
final String model;
Car(this.model); // Constructor that takes a model name
void displayModel() {
print('Car model: $model');
}
}
void main() {
final myCar = Car('Tesla Model S'); // Using `final` for object assignment
myCar.displayModel(); // Prints: Car model: Tesla Model S
// Uncommenting the following line will result in an error
// myCar = Car('BMW'); // Error: Cannot assign to the final variable 'myCar'
}
dart
Copy code
class Circle {
final double radius;
const Circle(this.radius); // `const` constructor
double area() => 3.14159 * radius * radius;
}
void main() {
const circle1 = Circle(10.0); // Using `const` constructor to create a compile-time constant object
print('Area of circle: ${circle1.area()}'); // Prints: Area of circle: 314.159
// Uncommenting the following line will result in an error
// circle1 = Circle(15.0); // Error: Can't assign to the const variable 'circle1'
}
dart
Copy code
void main() {
const double taxRate = 0.07; // `const` for a compile-time constant value
final double price = 100.0; // `final` because it is set at runtime
final double totalPrice = price + (price * taxRate); // final total calculation
print('Total Price: \$${totalPrice}'); // Prints: Total Price: $107.0
}
final Variables:
Assigned once: A variable declared as final can only be assigned once, but its value can be computed at runtime.
Mutable data: You can modify the contents of a final collection like a List, but you cannot reassign the variable itself.
const Variables:
Compile-time constants: The value of a const variable is known at compile-time, and it cannot change at runtime.
Immutable collections: When using const, the entire collection (like List or Map) is immutable, meaning both the collection reference and its contents cannot be modified.
final: Use it when you know the variable will be assigned only once but the value might be determined at runtime (e.g., user input, function results).
const: Use it when you need compile-time constants, such as mathematical constants or pre-defined immutable objects and collections.