On this page22 sections
- Prerequisites
- Connection With Previous Lectures
- Learning Objectives
- 1. You Have Been Using Objects All Along
- 2. State and Behaviour
- 3. A Class Is the Blueprint
- 4. Your First Class
- 5. Giving an Object Its Own Data
- 6. Adding Behaviour: a Method
- 7. A Method That Changes State
- 8. Why a Class Beats a Map
- 9. The Four Pillars of OOP
- 10. A Real-World Example
- Code Examples
- Common Beginner Mistakes
- Best Practices
- Mini Challenge
- Practice Questions
- Practice Answers
- Quick Revision
- Key Takeaways
- What's Next?
Lecture 52 — OOP Fundamentals
| Category | 9 — Object-Oriented Programming |
| Lecture | 052 of 140 |
| Estimated video length | 10 min |
| Target | Dart 3.12.2 |
| Level | Beginner |
A map can hold a student's name and age, but Dart cannot check it: a misspelled key gives
nulland every value loses its type. A class describes the record once, and Dart checks every use of it.
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–051:
- variables, types and naming conventions (Lectures 004–007)
- that every value in Dart is an
Object(Lecture 011) - functions with parameters and return values (Lectures 030–033)
- lists,
for-inloops and maps (Lectures 039–050) - records stored as
List<Map<…>>(Lecture 051)
Connection With Previous Lectures
In Lecture 051 we stored records in maps. Here is a student:
void main() {
var ali = {'name': 'Ali', 'age': 20};
print(ali['name']);
print(ali['nmae']);
}Ali
nullThe typo 'nmae' is not an error — just a silent null. And because the map mixes a String
and an int, Dart types every value as Object, so even simple arithmetic fails:
void main() {
var ali = {'name': 'Ali', 'age': 20};
// print(ali['age'] + 1); // ✗ the value's type is Object?, not int
}Error: The operator '+' isn't defined for the type 'Object?'.We need a way to say "a student has a String name and an int age" — once — and have Dart
check every use. That is what a class does.
Learning Objectives
By the end of this lecture you will be able to:
- Explain what an object is, in terms of state and behaviour
- Explain the difference between a class and an object
- Write a small class with fields and a method
- Create several objects from one class and change each one separately
- Call a method on an object and explain which object's data it uses
- Explain why a class is safer than a map for a record
- Name the four pillars of object-oriented programming
- Recognize the errors Dart gives for common class mistakes
1. You Have Been Using Objects All Along
An object is a value that bundles data with actions that work on that data. Every string and list you have used is one.
void main() {
var name = 'Sara';
print(name.length);
print(name.toUpperCase());
var marks = [80, 75];
marks.add(90);
print(marks.length);
}4
SARA
3The string knows its own length and can make an uppercase copy. The list knows its
elements and can add one. The dot . reaches into an object for its data or its actions.
2. State and Behaviour
Every object has two sides:
- State — the data it holds right now (a list's elements, an account's balance).
- Behaviour — what it can do (add an element, deposit money).
| Thing | State | Behaviour |
|---|---|---|
| Student | name, age, marks | introduce, calculate average |
| Bank account | owner, balance | deposit, withdraw |
| Shopping cart | items, prices | add item, calculate total |
| Thermometer | temperature in °C | convert to °F |
Object-oriented programming (OOP) is the habit of modelling a program as objects like these, each looking after its own state.
3. A Class Is the Blueprint
A class describes a kind of object: which data it holds and what it can do. An object created from a class is called an instance of it.
Analogy — a class is the architect's blueprint for a house; an object is a house built from it. One blueprint, many houses — and painting one house does not repaint the others.
String and List are classes written by the Dart team. 'Sara' is one instance of
String, and runtimeType (Lecture 010) names the class of any value:
void main() {
print('Sara'.runtimeType);
print([80, 75].runtimeType);
}String
List<int>Now we will write a class of our own.
4. Your First Class
A class is written with the keyword class, a name in UpperCamelCase, and a body in
braces. Variables inside a class are called fields:
class Student {
String name = '';
int age = 0;
}
void main() {
var ali = Student();
print(ali.name);
print(ali.age);
}
0Student() — the class name followed by () — creates a new object. The fields start
with their default values, so name is the empty string (the blank first line) and age is
0. Classes are written at the top level, outside main().
5. Giving an Object Its Own Data
Use the dot to read and change an object's fields. Each object has its own copy of every field:
class Student {
String name = '';
int age = 0;
}
void main() {
var ali = Student();
ali.name = 'Ali';
ali.age = 20;
var sara = Student();
sara.name = 'Sara';
sara.age = 18;
print('${ali.name} is ${ali.age}');
print('${sara.name} is ${sara.age}');
}Ali is 20
Sara is 18One class, two objects, two separate sets of data. Setting all fields one line at a time is clumsy; Lecture 054 — Constructors gives an object its values at the moment it is created.
6. Adding Behaviour: a Method
A function written inside a class is called a method. A method can use the object's fields directly by name:
class Student {
String name = '';
int age = 0;
void introduce() {
print('Hi, I am $name and I am $age.');
}
}
void main() {
var ali = Student();
ali.name = 'Ali';
ali.age = 20;
ali.introduce();
}Hi, I am Ali and I am 20.ali.introduce() runs the method for ali, so name inside it means ali.name.
7. A Method That Changes State
Methods can change the object's fields and return values, just like the functions of Lecture 030:
class BankAccount {
String owner = '';
int balance = 0;
void deposit(int amount) {
balance = balance + amount;
}
bool canAfford(int price) {
return balance >= price;
}
}
void main() {
var account = BankAccount();
account.owner = 'Sara';
account.deposit(500);
account.deposit(250);
print('${account.owner}: ${account.balance}');
print(account.canAfford(1000));
}Sara: 750
falseThe data (balance) and the rules that change it (deposit) now live together. Anyone who
wants to know how a balance changes looks in one place: the class.
8. Why a Class Beats a Map
Back to the problems from the start. With a class, a typo is a compile-time error instead of
a silent null:
class Student {
String name = '';
int age = 0;
}
void main() {
var ali = Student();
// print(ali.nmae); // ✗ there is no field called nmae
}Error: The getter 'nmae' isn't defined for the type 'Student'.Each field keeps its own type, so ali.age + 1 just works — and a wrong value is caught:
class Student {
String name = '';
int age = 0;
}
void main() {
var ali = Student();
print(ali.age + 1);
// ali.age = 'twenty'; // ✗ age is an int
}1Error: A value of type 'String' can't be assigned to a variable of type 'int'.| Map record | Class | |
|---|---|---|
| Misspelled name | silent null | compile-time error |
| Field types | one shared type (often Object) | each field its own type |
| Behaviour | separate functions | methods on the object |
| Required fields | anyone can forget a key | every object has every field |
Maps are still the right choice for lookups by key (Lecture 051). For a record with fixed fields, use a class.
9. The Four Pillars of OOP
Object-oriented programming rests on four ideas. You only need their names today — each one has its own lectures:
| Pillar | Idea in one sentence | Studied in |
|---|---|---|
| Encapsulation | An object protects its own data and lets others change it only through its methods. | Lecture 057 — Private Members & Encapsulation |
| Inheritance | A new class can build on an existing class and reuse what it has. | Lecture 059 — Inheritance |
| Polymorphism | Different objects can answer the same method call in their own way. | Lecture 065 — Polymorphism |
| Abstraction | Code depends on what an object can do, not how it does it. | Lectures 062 — Abstract Classes and 063 — Interfaces |
The BankAccount above already hints at encapsulation: deposit is the "proper" way to
change balance. Right now nothing stops someone writing account.balance = 1000000;
Lecture 057 shows how to forbid that.
10. A Real-World Example
A class with a list field and a method that calculates from it, used for several students:
class Student {
String name = '';
List<int> marks = [];
double average() {
var total = 0;
for (final mark in marks) {
total += mark;
}
return total / marks.length;
}
}
void main() {
var ali = Student();
ali.name = 'Ali';
ali.marks = [80, 75, 85];
var sara = Student();
sara.name = 'Sara';
sara.marks = [92, 88, 95];
for (final student in [ali, sara]) {
print('${student.name}: ${student.average()}');
}
}Ali: 80.0
Sara: 91.66666666666667Compare Lecture 051's Map<String, List<int>>: the same data, but now each student is one
typed object that can calculate its own average. A List<Student> holds them like any other
value.
Code Examples
Example 1 — A Class with Two Fields
class Book {
String title = 'Untitled';
int pages = 0;
}
void main() {
var book = Book();
print(book.title);
print(book.pages);
}Untitled
0Example 2 — Changing Fields
class Book {
String title = 'Untitled';
int pages = 0;
}
void main() {
var book = Book();
book.title = 'Dart Basics';
book.pages = 240;
print('${book.title}: ${book.pages} pages');
}Dart Basics: 240 pagesExample 3 — Two Objects Are Independent
class Counter {
int count = 0;
}
void main() {
var a = Counter();
var b = Counter();
a.count = 5;
print(a.count);
print(b.count);
}5
0Example 4 — A Method That Prints
class Dog {
String name = '';
void bark() {
print('$name says woof');
}
}
void main() {
var dog = Dog();
dog.name = 'Rex';
dog.bark();
}Rex says woofExample 5 — A Method That Returns a Value
class Rectangle {
double width = 0;
double height = 0;
double area() {
return width * height;
}
}
void main() {
var room = Rectangle();
room.width = 4;
room.height = 3.5;
print(room.area());
}14.0Example 6 — A Method That Changes a Field
class Counter {
int count = 0;
void increment() {
count++;
}
}
void main() {
var clicks = Counter();
clicks.increment();
clicks.increment();
clicks.increment();
print(clicks.count);
}3Example 7 — Student Report
class Student {
String name = '';
int mark = 0;
bool passed() {
return mark >= 50;
}
}
void main() {
var zayan = Student();
zayan.name = 'Zayan';
zayan.mark = 64;
print('${zayan.name} passed: ${zayan.passed()}');
}Zayan passed: trueExample 8 — Shopping Cart
class Cart {
List<int> prices = [];
void add(int price) {
prices.add(price);
}
int total() {
var sum = 0;
for (final price in prices) {
sum += price;
}
return sum;
}
}
void main() {
var cart = Cart();
cart.add(120);
cart.add(250);
cart.add(90);
print('Items: ${cart.prices.length}');
print('Total: ${cart.total()}');
}Items: 3
Total: 460Example 9 — Bank Account
class BankAccount {
int balance = 0;
void deposit(int amount) {
balance += amount;
}
void withdraw(int amount) {
if (amount <= balance) {
balance -= amount;
} else {
print('Not enough money');
}
}
}
void main() {
var account = BankAccount();
account.deposit(1000);
account.withdraw(300);
account.withdraw(900);
print('Balance: ${account.balance}');
}Not enough money
Balance: 700The rule "you cannot withdraw more than you have" lives inside the class, next to the data it protects.
Example 10 — Thermometer
class Thermometer {
double celsius = 0;
double fahrenheit() {
return celsius * 9 / 5 + 32;
}
}
void main() {
var lahore = Thermometer();
lahore.celsius = 35;
print('${lahore.celsius} °C = ${lahore.fahrenheit()} °F');
}35.0 °C = 95.0 °FCommon Beginner Mistakes
1. Forgetting the parentheses
class Student {
String name = '';
}
void main() {
var ali = Student; // no () — this is the class itself, not a new object
// ali.name = 'Ali'; // ✗
}Error: The setter 'name' isn't defined for the type 'Type'.Student() creates an object; Student alone names the class.
2. A field without a starting value
class Student {
// String name; // ✗ a String cannot start as null
}Error: Field 'name' should be initialized because its type 'String' doesn't allow null.The same rule as top-level variables in Lecture 004. Give it a default for now; Lecture 054 shows how a constructor supplies the value instead.
3. Calling a method on the class instead of an object
class Student {
String name = '';
void introduce() {
print('Hi, I am $name');
}
}
void main() {
// Student.introduce(); // ✗ which student?
}Error: Member not found: 'Student.introduce'.Create an object first and call the method on it: Student().introduce().
4. Writing a class inside main()
void main() {
// class Student {} // ✗ classes live at the top level
}Error: 'class' can't be used as an identifier because it's a keyword.Inside a function, Dart reads class as an ordinary name and gets confused. Move the class
outside main().
5. Misspelling a field name
ali.nmae gives Error: The getter 'nmae' isn't defined for the type 'Student'. — a good
error: the same typo in a map would have given a silent null.
Best Practices
- Name classes in UpperCamelCase (
BankAccount) and fields and methods in lowerCamelCase (balance,deposit). - One class should describe one thing.
- Name fields with nouns (
balance) and methods with verbs (deposit,calculateTotal). - Put the rules that change a field in a method of the same class, not scattered in
main(). - Use a class for records with fixed fields, and a map for lookups by key.
Mini Challenge
Write a Player class with a name (default '') and a score (default 0), and a method
addPoints(int points). Create Ali, give him 10 points and then 15 more, and print:
Ali: 25Try it yourself before opening the solution.
Show solution
class Player {
String name = '';
int score = 0;
void addPoints(int points) {
score += points;
}
}
void main() {
var ali = Player();
ali.name = 'Ali';
ali.addPoints(10);
ali.addPoints(15);
print('${ali.name}: ${ali.score}');
}Ali: 25Practice Questions
Beginner
- For a car, name two pieces of state and two behaviours.
- Write a class
Citywith a fieldname(default''). Create one, set its name to'Lahore', and print it. - Create two
Cityobjects named'Lahore'and'Karachi'and print both names. - What does
Studentmean on its own, and what doesStudent()mean?
Application
- Write a class
Circlewith adouble radius = 0and a methoddouble area()that returns3.14 * radius * radius. Print the area for radius10. - Write a class
Lampwithbool isOn = falseand a methodtoggle()that flips it. Toggle a lamp three times and printisOn. - Write a class
Productwithnameandprice, and a methodint priceFor(int quantity). Create tea at120and print the price for3. - Name the four pillars of OOP and the lecture where each is studied.
Challenge
- Write a class
Walletwithint balance = 0and a methodbool pay(int amount)that subtracts the amount and returnstrueonly if there is enough money, otherwise returnsfalsewithout changing anything. Deposit500by settingbalance, then pay200and then400, printing each result and the final balance. - Write a class
Studentwith anameandList<int> marks, and a methodint highest(). Create Sara with marks[72, 95, 88]and printSara: 95.
Practice Answers
Question 1 — Solution
State: colour, speed, fuel level. Behaviour: accelerate, brake, refuel. (Any two of each.)
Question 2 — Solution
class City {
String name = '';
}
void main() {
var city = City();
city.name = 'Lahore';
print(city.name);
}LahoreQuestion 3 — Solution
class City {
String name = '';
}
void main() {
var a = City();
var b = City();
a.name = 'Lahore';
b.name = 'Karachi';
print(a.name);
print(b.name);
}Lahore
KarachiQuestion 4 — Solution
Student names the class — the blueprint. Student() creates a new object from it.
Question 5 — Solution
class Circle {
double radius = 0;
double area() {
return 3.14 * radius * radius;
}
}
void main() {
var circle = Circle();
circle.radius = 10;
print(circle.area());
}314.0Question 6 — Solution
class Lamp {
bool isOn = false;
void toggle() {
isOn = !isOn;
}
}
void main() {
var lamp = Lamp();
lamp.toggle();
lamp.toggle();
lamp.toggle();
print(lamp.isOn);
}trueQuestion 7 — Solution
class Product {
String name = '';
int price = 0;
int priceFor(int quantity) {
return price * quantity;
}
}
void main() {
var tea = Product();
tea.name = 'tea';
tea.price = 120;
print(tea.priceFor(3));
}360Question 8 — Solution
Encapsulation (Lecture 057), inheritance (Lecture 059), polymorphism (Lecture 065) and abstraction (Lectures 062 and 063).
Question 9 — Solution
class Wallet {
int balance = 0;
bool pay(int amount) {
if (amount > balance) {
return false;
}
balance -= amount;
return true;
}
}
void main() {
var wallet = Wallet();
wallet.balance = 500;
print(wallet.pay(200));
print(wallet.pay(400));
print(wallet.balance);
}true
false
300Question 10 — Solution
class Student {
String name = '';
List<int> marks = [];
int highest() {
var best = marks[0];
for (final mark in marks) {
if (mark > best) {
best = mark;
}
}
return best;
}
}
void main() {
var sara = Student();
sara.name = 'Sara';
sara.marks = [72, 95, 88];
print('${sara.name}: ${sara.highest()}');
}Sara: 95Quick Revision
- What two things does every object have?
- What is the difference between a class and an object?
- What is a field? What is a method?
- What does
Student()do? - If two objects come from the same class, does changing one change the other?
- Why is
ali.nmaebetter thanali['nmae']? - Name the four pillars of OOP.
Key Takeaways
- An object bundles state (data) with behaviour (actions).
- A class is the blueprint; each object made from it is an instance.
- Strings and lists are objects too —
StringandListare classes. - Fields are variables in a class; methods are functions in a class.
ClassName()creates a new object; the dot reads fields and calls methods.- Every object has its own copy of the fields, and a method works on the object it is called on.
- A class gives each field its own type and turns typos into compile-time errors.
- The four pillars — encapsulation, inheritance, polymorphism, abstraction — each get their own lectures.
What's Next?
Lecture 53 — Creating Classes & Objects. You have seen the idea and a first class. Next we look closely at how classes and objects work in Dart: fields, methods, creating instances, setting fields with the cascade operator, and what really happens when two variables refer to the same object.