Inheritance, Abstract Classes and Interfaces
13.1 Inheritance
Single inheritance (extends). @override documents overrides (the analyzer checks it). super calls the parent.
class Animal {
final String name;
Animal(this.name);
String speak() => '...';
String describe() => '$name says ${speak()}';
}
class Dog extends Animal {
final String breed;
Dog(super.name, this.breed);
@override
String speak() => 'Woof';
}
class Puppy extends Dog {
Puppy(String name) : super(name, 'Unknown');
@override
String speak() => '${super.speak()} (squeaky)';
}
void main() {
final List<Animal> animals = [Dog('Rex', 'Lab'), Puppy('Bit')];
for (final a in animals) print(a.describe()); // polymorphism
}13.2 Abstract Classes
abstract class Shape {
double get area; // abstract getter
double perimeter(); // abstract method
String describe() => '${runtimeType}: area=${area.toStringAsFixed(2)}'; // concrete method
}
class Circle extends Shape {
final double radius;
Circle(this.radius);
@override
double get area => 3.14159 * radius * radius;
@override
double perimeter() => 2 * 3.14159 * radius;
}13.3 Implicit Interfaces
Every class defines an implicit interface. implements requires you to provide all members (no implementation is inherited).
class Logger {
void log(String msg) => print(msg);
}
class FileLogger implements Logger { // must implement log()
@override
void log(String msg) { /* write to file */ }
}
abstract interface class Repository<T> { // pure interface (Dart 3 modifier)
Future<T?> findById(String id);
Future<void> save(T item);
}
class Flyer { void fly() => print('flying'); }
class Swimmer { void swim() => print('swimming'); }
class Duck implements Flyer, Swimmer { // multiple interfaces
@override void fly() => print('Duck flies');
@override void swim() => print('Duck swims');
}13.4 extends vs implements vs with
✅ (mixin code) Must override all members Calls super constructor Mixins have no constructors