In Dart, final and const are keywords used to define variables whose values cannot be changed after they are assigned. However, there are important differences between the two, and understanding these differences is crucial for effective programming.

Overview of finalin Dart

  • Definition:
    The final keyword is used to declare a variable that can be assigned only once. Once a final variable is assigned a value, it cannot be changed. However, the value can be determined at runtime.
  • Usage:
    Use final when you want to ensure that a variable cannot be reassigned after its initial assignment, but its value can be computed dynamically.

Example:

void main() {
  final String name = 'Alice'; // A final variable  
   // name = 'Bob'; // This will cause an error: The final variable 'name' can only be set once   
   print(name);
  
  final DateTime now = DateTime.now(); // Value assigned at runtime  
   print('Current Time: $now');
}

Overview of constin Dart

  • Definition:
    The const keyword is used to declare compile-time constants. A const variable must be assigned a value that is known at compile time and cannot change throughout the program.
  • Usage:
    Use const when you want to define a value that is fixed and known ahead of time. This can help with memory optimization, as Dart can reuse the same instance for const objects.

Example:

void main() {
  const double pi = 3.14; // A compile-time constant 
    // pi = 3.14159; // This will cause an error: The const variable 'pi' can't be reassigned 
     print('Value of Pi: $pi');
  
  const List<int> numbers = [1, 2, 3]; // Compile-time constant list  
   // numbers.add(4); // This will cause an error: Cannot add to an unmodifiable list 
   }

Key Differences Between final and const

Featurefinalconst
InitializationMust be initialized at runtime.Must be initialized at compile time.
MutabilityThe reference cannot be changed, but the object can be mutable.The reference and the object are immutable.
Use CasesUse when the value is known only at runtime.Use when the value is known and fixed at compile time.
MemoryAllocated on the heap.Allocated in the compile-time constants pool.
Examplefinal currentDate = DateTime.now();const pi = 3.14;
   

 

Related Keywords

  1. var:

    • The var keyword is used to declare a variable without specifying its type. The type is inferred at runtime. var variables can be reassigned and can hold mutable or immutable values.

    Example:

    var message = 'Hello'; // Type inferred as String message = 'Hi'; // Allowed 
  2. dynamic:

    • The dynamic keyword allows you to declare a variable that can hold values of any type and can change types at runtime. Unlike final and const, dynamic variables can be reassigned and modified.

    Example:

    dynamic variable = 'Hello';
    variable = 5; // Allowed, as dynamic can change type 
  3. const Constructors:

    • You can use const with class constructors to create compile-time constants. This allows Dart to optimize memory usage by reusing instances.

    Example:

    class Point {
      final int x;
      final int y;
    
      const Point(this.x, this.y); // Const constructor }
    
    void main() {
      const p1 = Point(1, 2);
      const p2 = Point(1, 2); // Reuses the same instance as p1   
      print(identical(p1, p2)); // Output: true }

Best Practices

  1. Use final for Runtime Values:
    • Prefer final when the value is not known until runtime and you want to prevent reassignment.
  2. Use const for Compile-Time Constants:
    • Prefer const for values that are fixed and known ahead of time, especially when defining lists, maps, or other collections that won’t change.
  3. Readability:
    • Use descriptive names for your final and const variables to enhance code readability.
  4. Be Mindful of Mutability:
    • Remember that while final prevents reassignment, the underlying object can still be mutable. Use const if you want to ensure immutability.

Understanding Related Concepts

Runtime

Definition:
Runtime refers to the period during which a program is executing. It is when the code is run, and the program interacts with the system and user inputs.

  • Characteristics:
    • Errors occurring at runtime are known as runtime errors (e.g., null reference, division by zero).

Example:

void main() {
  int number;
  print(number); // This will cause a runtime error because 'number' is not initialized. }

Compile Time

Definition:
Compile time refers to the phase in which the source code is translated into machine code by the compiler. This phase checks for syntax errors and type checking before the code can be executed.

  • Characteristics:
    • Errors caught at this stage are known as compile-time errors (e.g., syntax errors, type mismatches).

Example:

void main() {
  int number = 'Hello'; // This will cause a compile-time error because a String cannot be assigned to an int. }

Mutable

Definition:
Mutable refers to objects or data structures that can be changed after they are created. This includes modifying the object's state, adding new elements, or changing existing ones.

  • Characteristics:
    • Mutable objects allow for modifications without creating a new instance.

Example:

void main() {
  List<String> fruits = ['Apple', 'Banana'];
  fruits.add('Cherry'); // Modifying the list   print(fruits); // Output: [Apple, Banana, Cherry] }

Immutable

Definition:
Immutable refers to objects or data structures that cannot be changed after they are created. Once an immutable object is initialized, its state cannot be modified.

  • Characteristics:
    • Immutable objects provide safety in concurrent programming since they cannot be altered.

Example:

void main() {
  const List<String> fruits = ['Apple', 'Banana'];
  // fruits.add('Cherry'); // This will cause an error: Cannot add to an unmodifiable list   print(fruits); // Output: [Apple, Banana] }

Summary of Terms

TermDefinitionExample
RuntimeThe period during which a program is executing.Errors like null reference occur at runtime.
Compile TimeThe phase when the source code is translated into machine code, checking for errors.Syntax errors like assigning a string to an int cause compile-time errors.
MutableObjects that can be modified after creation.Lists and maps that allow adding or changing items.
ImmutableObjects that cannot be changed after creation.const lists or strings that cannot be altered after initialization.

Conclusion

Understanding the differences between final and const is crucial for writing efficient and clear Dart code. Proper use of these keywords can help manage memory effectively and enforce immutability where needed. Additionally, grasping the concepts of runtime, compile time, mutable, and immutable will enhance your programming skills and contribute to better software design and implementation. This foundational knowledge will serve you well as you advance in your Dart programming journey and tackle more complex applications.

PLAY QUIZ

What does the final keyword do in Dart?

It allows a variable to be reassigned multiple times.

It declares a variable that can be assigned only once, with the value determined at runtime.

It creates a compile-time constant.

It initializes a variable with a default value.