Watch the video (12 min)
On this page27 sections
  1. Prerequisites
  2. Connection With Previous Lectures
  3. Learning Objectives
  4. 1. Values That Should Never Change
  5. 2. Declaring a final Variable
  6. 3. A final Variable Cannot Be Reassigned
  7. 4. final With an Explicit Type
  8. 5. A final Variable Can Hold a Calculated Value
  9. 6. Declare a final Now, Assign It Once Later
  10. 7. What Is const?
  11. 8. const Needs a Value Known Before the Program Runs
  12. 9. final vs const
  13. 10. Constants at the Top Level
  14. 11. late — Declare Now, Assign Before Use
  15. 12. Breaking the Promise
  16. 13. late final — Assign Once, Later
  17. 14. Choosing the Right Keyword
  18. 15. A Real-World Example
  19. Code Examples
  20. Common Beginner Mistakes
  21. Best Practices
  22. Mini Challenge
  23. Practice Questions
  24. Practice Answers
  25. Quick Revision
  26. Key Takeaways
  27. What's Next?

Lecture 06 — final, const & late

Category2 — Variables & Data Types
Lecture006 of 140
Estimated video length12 min
TargetDart 3.12.2
LevelBeginner

Every variable so far could be changed by any line of the program. final and const lock a value in place, and late lets you promise a value that arrives a little later.

Contents

Prerequisites · Connection · Objectives · Lesson · Code Examples · Common Mistakes · Best Practices · Mini Challenge · Practice Questions · Answers · Takeaways

Every error message in this lecture is real. Each one was produced by running the code shown on Dart 3.12.2, so you will recognize it when you meet it yourself.


Prerequisites

Students should already understand, from Lectures 001–005:

  • main(), print(), and string interpolation with $
  • declaring, initializing, and assigning variables
  • the types String, int, double, and bool
  • why a top-level variable must get its value where it is declared (Lecture 004)
  • declaring variables with var and how Dart infers their type (Lecture 005)

Connection With Previous Lectures

In Lecture 005, var worked out each variable's type for us. But a var variable can still be given a new value by any line of the program:

dart
void main() {
  var taxRate = 0.17;
  taxRate = 0.5; // a typo, or a mistake — Dart allows it
  print(taxRate);
}
output
0.5

Nothing stopped that second line. Yet many values should never change once they are set: a tax rate, a student's name on a report, the number of days in a week. We need a way to tell Dart "this value is fixed" — and have Dart refuse any line that tries to change it.


Learning Objectives

By the end of this lecture you will be able to:

  • Explain why some values should never change
  • Declare variables with final and const
  • Assign a final variable exactly once, even after its declaration
  • Explain the difference between final and const
  • Recognize which values can be const and which can only be final
  • Use late to declare a top-level variable whose value arrives later
  • Choose between var, final, const, and late
  • Recognize the error messages Dart produces for common mistakes with these keywords

1. Values That Should Never Change

A normal variable can be changed as often as you like. A final or constant variable is given its value once, and then that value stays the same for the rest of the program.

Analogy — a normal variable is a note written in pencil: you can erase it and write something new. A final or const variable is written in ink: once it is on the page, it stays.

Dart has two keywords for values written in ink: final and const.


2. Declaring a final Variable

Write final in place of var:

dart
void main() {
  final name = 'Ali';
  final age = 20;
  print(name);
  print(age);
}
output
Ali
20

Like var, final infers the type from the value: name is a String, age an int.


3. A final Variable Cannot Be Reassigned

Try to give a final variable a new value, and the program does not compile:

dart
void main() {
  final name = 'Ali';
  name = 'Sara';
  print(name);
}
output
Error: Can't assign to the final variable 'name'.
  name = 'Sara';
  ^^^^

Dart catches this before the program runs. The accidental tax-rate change from the Connection section is now impossible.


4. final With an Explicit Type

You can write the type after final:

dart
void main() {
  final String city = 'Lahore';
  final double balance = 1000;
  print(city);
  print(balance);
}
output
Lahore
1000.0

As in Lecture 004, 1000 in a double is stored as 1000.0. Write final alone or final plus a type — never final var.


5. A final Variable Can Hold a Calculated Value

The value of a final variable does not have to be typed out. It can be the result of a calculation that uses other variables:

dart
void main() {
  var price = 250;
  var quantity = 4;
  final total = price * quantity;
  print('Total: $total');
}
output
Total: 1000

The calculation happens while the program runs, and its result is locked into total.


6. Declare a final Now, Assign It Once Later

Inside a function, a final variable may be declared first and assigned later — exactly once:

dart
void main() {
  final String grade;
  grade = 'A';
  print(grade);
}
output
A

Assigning it a second time is an error:

dart
void main() {
  final String grade;
  grade = 'A';
  grade = 'B';
  print(grade);
}
output
Error: Final variable 'grade' might already be assigned at this point.
  grade = 'B';
  ^^^^^

And, just like the variables in Lecture 004, it cannot be read before it has a value:

dart
void main() {
  final String grade;
  print(grade);
}
output
Error: Final variable 'grade' must be assigned before it can be used.
  print(grade);
        ^^^^^

7. What Is const?

const also creates a variable that never changes. Write it the same way as final:

dart
void main() {
  const daysInWeek = 7;
  const taxRate = 0.17;
  print(daysInWeek);
  print(taxRate);
}
output
7
0.17

Changing a const is rejected in the same way:

dart
void main() {
  const taxRate = 0.17;
  taxRate = 0.2;
  print(taxRate);
}
output
Error: Can't assign to the const variable 'taxRate'.
  taxRate = 0.2;
  ^^^^^^^

8. const Needs a Value Known Before the Program Runs

A const value must be known when the program is compiled — before it starts running. That is why it is called a compile-time constant. Literal values and calculations made only from literals and other constants are fine:

dart
void main() {
  const minutesPerHour = 60;
  const secondsPerDay = 24 * minutesPerHour * 60;
  print(secondsPerDay);
}
output
86400

But a value that comes from a normal variable is only known while the program runs, so it cannot be const:

dart
void main() {
  var price = 100;
  const total = price * 3;
  print(total);
}
output
Error: Not a constant expression.
  const total = price * 3;
                ^^^^^

Surprisingly, the same error appears if price is final: final means "set once", not "known before the program runs". The fix is to make total a final variable, as in section 5 — or to make price a const too.


9. final vs const

finalconst
Can be reassigned?NoNo
Value decidedwhile the program runsbefore the program runs
Can use normal variables?YesNo — only literals and other constants
Can be assigned after declaration?Yes, once (inside a function)No — value on the same line
Examplefinal total = price * quantity;const daysInWeek = 7;

A simple way to remember it: every const is fixed, but not every fixed value can be a const. If you know the value while writing the code — 7 days, a 0.17 tax rate — use const. If the value has to be worked out first, use final.

const has more uses with lists and objects; we will meet them in Lecture 046 — Collection Features and Lecture 055 — Named & Constant Constructors.


10. Constants at the Top Level

final and const both work outside main(). As with every top-level variable, they must get their value right where they are declared:

dart
const appName = 'Dart Course';
const maxScore = 100;

void main() {
  print(appName);
  print('Maximum score: $maxScore');
}
output
Dart Course
Maximum score: 100

Notice the names. Some languages write constants in capitals, like MAX_SCORE. Dart's style guide uses lowerCamelCase for constants too: maxScore, appName, taxRate.


11. late — Declare Now, Assign Before Use

Lecture 004 showed that a top-level String name; without a value is an error. Sometimes, though, the value really is not available yet when you declare the variable. The late keyword tells Dart: "I promise to assign this before anyone reads it."

dart
late String userName;

void main() {
  userName = 'Sara';
  print('Welcome, $userName');
}
output
Welcome, Sara

Without late, the first line would be the error from Lecture 004. With late, Dart accepts the declaration and trusts your promise.

Why Dart needs this promise in the first place is part of null safety, which we study in Lectures 012–016. For now, read late as "the value comes later".


12. Breaking the Promise

Dart cannot always check a late promise before the program runs. If you read the variable before assigning it, the program compiles, starts, and then stops with an error:

dart
late String userName;

void main() {
  print(userName);
}
output
Unhandled exception:
LateInitializationError: Field 'userName' has not been initialized.

This is the first error in this course that happens while the program is running. Dart also prints several lines showing where it stopped; they are left out here. We will learn to read them in Category 14 — Error & Exception Handling. Use late only when you are sure the assignment happens first.


13. late final — Assign Once, Later

late and final can be combined. The result is a variable that gets its value later, and then never changes:

dart
late final String studentId;

void main() {
  studentId = 'STU-104';
  print('ID: $studentId');
}
output
ID: STU-104

A second assignment is caught while the program runs:

dart
late final String studentId;

void main() {
  studentId = 'STU-104';
  studentId = 'STU-200';
  print(studentId);
}
output
Unhandled exception:
LateInitializationError: Field 'studentId' has already been initialized.

late has one more use — delaying a calculation until the value is first needed — which makes sense once we have functions (Lecture 030) and classes (Lecture 053).


14. Choosing the Right Keyword

Start from the strictest keyword and loosen only when you must:

  1. const — the value is known while writing the code: const daysInWeek = 7;
  2. final — the value is set once but worked out while running: final total = price * quantity;
  3. var — the value really needs to change: var balance = 1000.0;
  4. late — only when a variable cannot get its value where it is declared.

Most variables in real Dart code are final; a var signals a value that is meant to change.


15. A Real-World Example

dart
const shopName = 'Corner Books';
const taxRate = 0.1;

late final String cashier;

void main() {
  cashier = 'Zayan';

  final book = 'Dart Basics';
  final price = 800;
  final quantity = 2;
  final subtotal = price * quantity;
  final tax = subtotal * taxRate;
  final total = subtotal + tax;

  var loyaltyPoints = 50;
  loyaltyPoints = loyaltyPoints + 16;

  print('$shopName — cashier: $cashier');
  print('$book x $quantity');
  print('Subtotal: $subtotal');
  print('Tax: $tax');
  print('Total: $total');
  print('Loyalty points: $loyaltyPoints');
}
output
Corner Books — cashier: Zayan
Dart Basics x 2
Subtotal: 1600
Tax: 160.0
Total: 1760.0
Loyalty points: 66

Each keyword has a job: the shop name and tax rate are known in advance (const), the cashier is set once in main() (late final), the receipt values are calculated once (final), and only the loyalty points change (var).


Code Examples

Example 1 — Basic final

dart
void main() {
  final name = 'Ali';
  final age = 20;
  print('Name: $name');
  print('Age: $age');
}
output
Name: Ali
Age: 20

Example 2 — final With Explicit Types

dart
void main() {
  final String name = 'Sara';
  final int age = 18;
  final double height = 5.6;
  final bool isStudent = true;
  print('$name, $age, $height, $isStudent');
}
output
Sara, 18, 5.6, true

Example 3 — final Assigned Once, Later

dart
void main() {
  final String result;
  result = 'Passed';
  print('Result: $result');
}
output
Result: Passed

Example 4 — Basic const

dart
void main() {
  const hoursInDay = 24;
  const pi = 3.14159;
  const greeting = 'Hello';
  print(hoursInDay);
  print(pi);
  print(greeting);
}
output
24
3.14159
Hello

Example 5 — const From Other Constants

dart
void main() {
  const daysInWeek = 7;
  const hoursInDay = 24;
  const hoursInWeek = daysInWeek * hoursInDay;
  print('Hours in a week: $hoursInWeek');
}
output
Hours in a week: 168

Example 6 — late at the Top Level

dart
late String language;

void main() {
  language = 'Dart';
  print('Learning $language');
}
output
Learning Dart

Example 7 — Student Marks

dart
const totalMarks = 300;

void main() {
  final student = 'Ali';
  final math = 80;
  final science = 75;
  final english = 85;
  final obtained = math + science + english;
  final percentage = obtained / totalMarks * 100;
  print('Student: $student');
  print('Obtained: $obtained / $totalMarks');
  print('Percentage: $percentage');
}
output
Student: Ali
Obtained: 240 / 300
Percentage: 80.0

How it works

  1. totalMarks is the same for every student and known in advance: a top-level const.
  2. The marks and obtained are set once: final.
  3. Division with / gives a double, so percentage prints as 80.0.

Example 8 — Shopping Total

dart
const deliveryFee = 150;

void main() {
  final product = 'Notebook';
  final price = 500;
  var quantity = 2;
  quantity = quantity + 1;
  final total = price * quantity + deliveryFee;
  print('Product: $product');
  print('Quantity: $quantity');
  print('Total: $total');
}
output
Product: Notebook
Quantity: 3
Total: 1650

How it works

  1. The delivery fee is a fixed rule of the shop: const.
  2. The customer changes their mind about the quantity, so quantity must be var.
  3. total is calculated once, after the quantity is settled: 500 * 3 + 150 is 1650.

Example 9 — Bank Balance

dart
const minimumBalance = 500.0;

late final String accountHolder;

void main() {
  accountHolder = 'Sara';
  var balance = 2000.0;
  balance = balance - 1200;
  final spendable = balance - minimumBalance;
  print('Account: $accountHolder');
  print('Balance: $balance');
  print('Spendable: $spendable');
}
output
Account: Sara
Balance: 800.0
Spendable: 300.0

How it works

  1. minimumBalance is a bank rule known in advance, so it is const.
  2. accountHolder is assigned once inside main(), then never changes: late final.
  3. balance changes after a withdrawal, so it is var.
  4. spendable is worked out once from the current balance: 800.0 - 500.0 is 300.0.

Example 10 — Temperature Conversion

dart
const freezingPoint = 32;

void main() {
  final celsius = 25.0;
  final fahrenheit = celsius * 9 / 5 + freezingPoint;
  print('Celsius: $celsius');
  print('Fahrenheit: $fahrenheit');
}
output
Celsius: 25.0
Fahrenheit: 77.0

How it works

  1. Water always freezes at 32 °F, so freezingPoint is const.
  2. celsius is final, so fahrenheit, calculated from it, can only be final too.

Common Beginner Mistakes

1. Trying to change a final variable

dart
void main() {
  final name = 'Ali';
  // name = 'Sara'; // ✗
}
output
Error: Can't assign to the final variable 'name'.

If the value genuinely needs to change, use var instead.

2. Assigning a final variable twice

dart
void main() {
  final String grade;
  grade = 'A';
  // grade = 'B'; // ✗
}
output
Error: Final variable 'grade' might already be assigned at this point.

A final variable may be assigned after its declaration, but only once.

3. Making a const from a variable

dart
void main() {
  final price = 100;
  // const total = price * 3; // ✗
}
output
Error: Not a constant expression.

const values must be known before the program runs. Use final total = price * 3;.

4. Declaring a const without a value

dart
void main() {
  // const int maxScore; // ✗
}
output
Error: The const variable 'maxScore' must be initialized.
Try adding an initializer ('= expression') to the declaration.

A const gets its value on the same line, always.

5. Writing final and var together

dart
void main() {
  // final var name = 'Ali'; // ✗
}
output
Error: Members can't be declared to be both 'final' and 'var'.
Try removing the keyword 'var'.

final already replaces var. Write final name = 'Ali'; or final String name = 'Ali';.

6. Reading a late variable before assigning it

dart
late String userName;

void main() {
  // print(userName); // ✗ before any assignment
}
output
LateInitializationError: Field 'userName' has not been initialized.

This one compiles and crashes while running. Assign first, read second.

7. Writing constants in capitals

MAX_SCORE compiles, but it is not Dart style. Write maxScore.


Best Practices

  • Prefer const when the value is known while writing the code.
  • Use final for any value that is set once — this covers most variables.
  • Use var only when the value really needs to change.
  • Give final and const variables their value on the declaration line whenever you can.
  • Use late sparingly, and assign it as early as possible.
  • Name constants in lowerCamelCase: taxRate, not TAX_RATE.

Mini Challenge

Write a program for Zayan's class test. The maximum mark is 50 and the pass mark is 20 — both known in advance. Zayan scores 38. Calculate how many marks he scored above the pass mark. Use const and final only — no var.

Your program should print exactly:

output
Student: Zayan
Score: 38 / 50
Above pass mark by: 18

Try it yourself before opening the solution.

Show solution
dart
const maxMarks = 50;
const passMark = 20;

void main() {
  final student = 'Zayan';
  final score = 38;
  final aboveBy = score - passMark;
  print('Student: $student');
  print('Score: $score / $maxMarks');
  print('Above pass mark by: $aboveBy');
}
output
Student: Zayan
Score: 38 / 50
Above pass mark by: 18

How it works

  1. maxMarks and passMark are rules of the test, known in advance: const.
  2. student, score, and the calculated aboveBy (38 - 20) are set once: final.

Practice Questions

Work through these in order — they run from beginner to application to challenge. Every question gives you exact values, so you can compare your output with the answers.

Beginner

  1. Use final to store the city 'Karachi' and print it.
  2. Use const to store monthsInYear = 12 and print it.
  3. Use final with explicit types to store name = 'Sara' (String) and balance = 1500 (double). Print both, each on its own line.

Application

  1. Store price = 450 and quantity = 2 with final, calculate the total with final, and print Total: 900.

  2. Use const to store minutesPerHour = 60 and hoursPerDay = 24, then calculate minutesPerDay as a const and print it.

  3. This program does not compile. Change one word so that it prints Total: 600:

    dart
    void main() {
      var price = 200;
      const total = price * 3;
      print('Total: $total');
    }
  4. Declare final String result; inside main(), assign it 'Pass' on the next line, and print Result: Pass.

  5. Declare a top-level late String teacher;. In main(), assign 'Mr. Ahmed' and print Teacher: Mr. Ahmed.

Challenge

  1. Ali's savings start at 1000. He adds 250, then adds 100. The bank pays a fixed bonus of 50, known in advance. Choose var, final, or const for each value, and print Savings: 1350 and With bonus: 1400.
  2. A temperature program stores the freezing point 0 and boiling point 100 of water in Celsius. Store today's temperature 36.6, then calculate how far it is from boiling. Print Below boiling by: 63.4. Explain in one sentence why the distance cannot be a const.

Practice Answers

Question 1 — Solution

dart
void main() {
  final city = 'Karachi';
  print(city);
}
output
Karachi

Question 2 — Solution

dart
void main() {
  const monthsInYear = 12;
  print(monthsInYear);
}
output
12

Question 3 — Solution

dart
void main() {
  final String name = 'Sara';
  final double balance = 1500;
  print(name);
  print(balance);
}
output
Sara
1500.0

1500 is stored in a double, so it prints as 1500.0.

Question 4 — Solution

dart
void main() {
  final price = 450;
  final quantity = 2;
  final total = price * quantity;
  print('Total: $total');
}
output
Total: 900

Question 5 — Solution

dart
void main() {
  const minutesPerHour = 60;
  const hoursPerDay = 24;
  const minutesPerDay = minutesPerHour * hoursPerDay;
  print(minutesPerDay);
}
output
1440

minutesPerDay is built only from constants, so it can be const too.

Question 6 — Solution

Change const to final, because total uses the normal variable price:

dart
void main() {
  var price = 200;
  final total = price * 3;
  print('Total: $total');
}
output
Total: 600

Question 7 — Solution

dart
void main() {
  final String result;
  result = 'Pass';
  print('Result: $result');
}
output
Result: Pass

Question 8 — Solution

dart
late String teacher;

void main() {
  teacher = 'Mr. Ahmed';
  print('Teacher: $teacher');
}
output
Teacher: Mr. Ahmed

Question 9 — Solution

dart
const bonus = 50;

void main() {
  var savings = 1000;
  savings = savings + 250;
  savings = savings + 100;
  final withBonus = savings + bonus;
  print('Savings: $savings');
  print('With bonus: $withBonus');
}
output
Savings: 1350
With bonus: 1400

Question 10 — Solution

dart
const freezingPoint = 0;
const boilingPoint = 100;

void main() {
  final today = 36.6;
  final belowBoiling = boilingPoint - today;
  print('Freezing point: $freezingPoint');
  print('Below boiling by: $belowBoiling');
}
output
Freezing point: 0
Below boiling by: 63.4

The distance uses today, a final variable, and a const may use only values known before the program runs.


Quick Revision

  1. What is the difference between a var variable and a final variable?
  2. Can a final variable be declared on one line and assigned on a later line?
  3. When is a const value decided?
  4. Why can const total = price * 3; fail even when price is final?
  5. What naming style does Dart use for constants?
  6. What does late promise?
  7. When does a broken late promise cause an error — before or while the program runs?
  8. Which keyword should you reach for first: const, final, or var?

Key Takeaways

  • final and const create variables that cannot be reassigned.
  • final is set once; its value can be worked out while the program runs.
  • A final variable inside a function may be assigned after its declaration — exactly once.
  • const is a compile-time constant: its value must be known before the program runs.
  • A const can use only literals and other constants — not var or final variables.
  • Constants use lowerCamelCase names, like every other variable.
  • late lets you declare a variable now and assign it before it is read; reading it too early stops the running program with a LateInitializationError.
  • Prefer const, then final, then var; use late only when you must.

What's Next?

Lecture 07 — Dart Data Types. We have been using String, int, double, and bool since Lecture 004. Next we look at Dart's data types properly: what each type can store, how they relate to each other, and which other types Dart offers beyond these four.


Video lecture

Subscribe
Placeholder video — the real recording isn't linked yet.