Inheritance and Overriding
When several classes need to share the same starting point, rewriting the same code in each one gets tiring and error-prone. Dart solves this with inheritance. Inheritance lets one class build on another: the new class automatically gets the fields and methods of the class it builds on, and can add its own or replace some of them.
The class you start from is called the parent (or superclass). The class you create from it is the child (or subclass). The keyword is extends: a child extends its parent.
Here is a small example. A Vehicle class holds what every vehicle has. A Car class extends it and adds something extra.
class Vehicle {
int wheels;
Vehicle(this.wheels);
String describe() => 'I have $wheels wheels';
}
class Car extends Vehicle {
String horn;
Car(this.horn) : super(4); // pass wheels up to the parent
void honk() => print('$horn!');
}
void main() {
final car = Car('beep');
print(car.describe()); // inherited from Vehicle
car.honk(); // added by Car
}Notice two things. First, car.describe() works even though Car never defined it — the child inherits it. Second, Car's constructor calls super(4). The word super refers to the parent class; here it hands the value 4 to the parent's constructor.
Overriding: Replacing Inherited Behavior
Sometimes a child should behave differently from its parent. Overriding means writing a method in the child with the same name, replacing the parent's version. In Dart you must mark it with @override so the tool can check you actually matched a real parent method — this catches typos early.
class Animal {
String speak() => '...';
}
class Dog extends Animal {
@override
String speak() => 'Woof!';
}
void main() {
final Animal pet = Dog();
print(pet.speak()); // Woof! — the child's version wins
}Even though the variable is typed as Animal, Dart runs the Dog version at runtime. This is called polymorphism: the same call behaves differently depending on the actual object.
A Child Can Reuse the Parent's Version
An overriding method can also call the parent's version with super, then add to it:
class Truck extends Vehicle {
Truck() : super(6);
@override
String describe() => '${super.describe()} and I haul heavy loads';
}One Parent Only
Dart allows a class to extend exactly one parent — no multiple inheritance. If you need to share behavior from several sources, Dart offers mixins, which a later chapter covers.
Show diagram source
classDiagram
Animal <|-- Dog
Animal <|-- Cat
Animal : speak()
Dog : speak()
Cat : speak()Exercise
What does the @override annotation do, and why is it useful?
Show answer
It marks a method as intentionally replacing an inherited one. The analyzer then checks that a matching method exists in the parent, so a misspelled name or wrong signature is caught as an error instead of silently creating a new method.
Exercise
In a child class, how can you run the parent's constructor or the parent's version of an overridden method?
Show answer
Use the super keyword: super(args) in the constructor's initializer list to call the parent constructor, and super.methodName() inside a method body to reuse the parent's implementation.
Spotted a mistake, or code that does not work?