Skip to content

Beginner · Null safety and object-oriented Dart · topic 7 of 50 · 30 min

Inheritance, interfaces, mixins and extensions

Explanation

extends creates a subclass that inherits and can override (@override) members; super calls the parent. Abstract classes define members subclasses must implement. Every class is also an implicit interface that other classes can implement. Mixins (mixin ... with) share behaviour across unrelated classes, and extension methods add functions to existing types like String without changing them.

Inheritance with extends

Inheritance lets a subclass reuse a parent class and change only what differs. In Flutter, your screens extend StatelessWidget or StatefulWidget and override build. A class can extend only one class.

dart
class Ticket {
  final String passenger;
  final int baseFare;
  Ticket(this.passenger, this.baseFare);
  int total() => baseFare;
  String summary() => '$passenger: Rs ${total()}';
}

class TrainTicket extends Ticket {
  final bool tatkal;
  TrainTicket(super.passenger, super.baseFare, {this.tatkal = false});

  @override
  int total() => tatkal ? baseFare + 300 : baseFare;
}

void main() {
  final List<Ticket> all = [Ticket('Asha', 500), TrainTicket('Ravi', 1200, tatkal: true)];
  for (final t in all) print(t.summary());   // Asha: Rs 500, Ravi: Rs 1500
}
super.passenger forwards the parameter to the parent constructor (Dart 2.17+). @override marks a replaced method.

The List<Ticket> holds both kinds of ticket. When the loop calls summary(), each object uses its own version of total(). This is polymorphism: one call, different behaviour depending on the actual object.

Abstract classes

dart
abstract class Shape {
  double area();                       // no body: subclasses must implement
  String describe() => 'Area: ${area().toStringAsFixed(2)}';
}

class Circle extends Shape {
  final double r;
  Circle(this.r);
  @override
  double area() => 3.14159 * r * r;
}
You cannot create a Shape directly, only its subclasses.

Implicit interfaces: implements

In Dart, every class also defines an interface: the list of its public members. Another class can promise to provide all of them with implements, without inheriting any code. This is how you create fakes for testing: class FakePaymentService implements PaymentService.

dart
abstract class PaymentService {
  Future<bool> pay(int paise);
}

class UpiPaymentService implements PaymentService {
  @override
  Future<bool> pay(int paise) async => true;     // would call a real gateway
}

class FakePaymentService implements PaymentService {
  @override
  Future<bool> pay(int paise) async => paise < 1000000;   // predictable for tests
}
Code that depends on PaymentService works with either.

Mixins: sharing behaviour

A mixin is a bundle of methods and fields that can be added to several unrelated classes with the with keyword. A class can use many mixins. Flutter uses mixins for things like SingleTickerProviderStateMixin in animations (module 9).

dart
mixin Loggable {
  void log(String message) => print('[${runtimeType}] $message');
}

class OrderService with Loggable {
  void place() => log('Order placed');
}

class CartService with Loggable {
  void clear() => log('Cart cleared');
}
Both services get log without sharing a parent class.

Extension methods

An extension adds methods or getters to an existing type, even one you did not write, such as String or int. It does not change the class; it is resolved at compile time from the static type.

dart
extension IndianFormat on int {
  String get rupees => 'Rs $this';
}

extension Initials on String {
  String get initials => split(' ').where((w) => w.isNotEmpty).map((w) => w[0].toUpperCase()).join();
}

void main() {
  print(499.rupees);                  // Rs 499
  print('rahul kumar'.initials);      // RK
}
Import the file that declares an extension to use it.
ToolRelationshipUse for
extendsis a (one parent)Specialising a base class, Flutter widgets
implementscan do (promise all members)Swappable services, fakes for tests
with (mixin)has the abilitySharing behaviour across unrelated classes
extensionadds to an existing typeHelpers on String, int, BuildContext
Think of it like this: extends is a child inheriting the family business. implements is a franchise agreement: you promise to offer every item on the brand's menu, cooked your own way. A mixin is hiring a skilled accountant who can work for any shop. An extension is a sticker you add to your own copy of a book, without changing the printed book.

Common mistakes

  • Forgetting @override: allowed but discouraged; the annotation catches typos in method names.
  • Deep inheritance trees for code reuse. Prefer composition, mixins or small helper classes.
  • Using implements and expecting to inherit code: you must implement every member yourself.
  • Forgetting to import the file that defines an extension: "The getter isn't defined".

Need help?

Stuck on a word or an idea? Search this course, or every course, and jump straight to the explanation or a worked question.

Try:

Watch the lesson

Inheritance, interfaces, mixins and extensions · 1/6

class TrainTicket extends Ticket {
  @override
  int total() => baseFare + 300;
}

extends creates a subclass. Override changes a method. super calls the parent.

Prefer a video by a teacher? Find free videos on “dart inheritance abstract class implements mixin extension methods” on YouTube ↗

In real life: Swappable SMS providers

A clinic appointment app sends reminders by SMS. An abstract SmsSender defines send(phone, text). One class implements it with the clinic's SMS gateway, another with a fake used in tests and demos. A Loggable mixin adds logging to both, and an extension on String formats Indian phone numbers. Changing gateways later touches one class only.

dart
abstract class SmsSender { Future<void> send(String phone, String text); }

mixin Loggable { void log(String m) => print('LOG: $m'); }

class FakeSmsSender with Loggable implements SmsSender {
  @override
  Future<void> send(String phone, String text) async => log('to $phone: $text');
}

extension PhoneFormat on String {
  String get e164 {
    final digits = replaceAll(RegExp(r'\D'), '');
    return '+91${digits.length > 10 ? digits.substring(digits.length - 10) : digits}';
  }
}
Patterns combined: interface, mixin and extension. "98765 43210".e164 gives +919876543210.

Practice (0/3 done)

Task 1 · Question

What does this print? class A { String hi() => 'A'; } class B extends A { @override String hi() => 'B' + super.hi(); } void main() { A x = B(); print(x.hi()); }

Task 2 · Question

You need a fake of ApiClient for tests without inheriting its real network code. Which keyword?

Task 3 · Practice

Create an abstract class Discount with int apply(int price). Implement FlatDiscount(amount) and PercentDiscount(percent). Add a mixin Describable with describe() that prints runtimeType, and an extension on int with a getter rupees. Apply both discounts to 1000 and print the results with the extension.

Quick quiz

Question 1

1.How many classes can a Dart class extend?

Question 2

2.Which keyword adds a mixin?

Question 3

3.What does an extension method change in the original class?

Question 4

4.Which statement about implicit interfaces is true?

Read more (free)

Before this, learn

This topic builds on these. If something here feels new, open them first.

Open a question to see the answer and why. The first ones are this topic's own quiz, so try the quiz above before you peek.

How many classes can a Dart class extend?

Answer: One

Single inheritance; many interfaces and mixins.

Which keyword adds a mixin?

Answer: with

class X with MyMixin.

What does an extension method change in the original class?

Answer: Nothing; it adds methods usable where the extension is imported

Extensions are compile-time helpers.

Which statement about implicit interfaces is true?

Answer: Every class defines an interface other classes can implement

Any class can be implemented.

How many classes can a Kotlin class extend?Related

Answer: One

One superclass, but many interfaces.

From Inheritance and interfaces

How many classes can a Java class directly extend?Related

Answer: One

Java has single inheritance for classes.

From Inheritance with extends

Which keyword creates a compile-time constant?Related

Answer: const

const values are known at compile time.

From Interview questions: Dart

class B extends A {} (no constructor). What does new B(1, 2) do?Related

Answer: Calls A's constructor with 1, 2

A missing constructor in a subclass passes all arguments to super automatically.

From Inheritance and composition

Pass the quiz (60% or more) or mark this topic as done when you are ready.

Your progress is saved on this device only.

Next steps

  1. 1 more topic in “Null safety and object-oriented Dart” before its exam: Dart 3: enums, records, patterns and sealed classes.
  2. Module 2 exam: Null safety and object-oriented Dart · 13 questions · 25 min, without help. 4 topics of this module still to finish first.
  3. Then the next module, Async Dart and packages. 50 topics left in the course before the final exam.

← Previous: Classes and constructors