Dart Inheritance and Mixins

Inheritance lets one class borrow the features of another. A mixin lets a class borrow features from several sources. Flutter itself relies on both ideas: every widget you write inherits from StatelessWidget or State, and many helper behaviors arrive through mixins.

Inheritance with extends

A child class receives every property and method of its parent. Think of a family recipe: the grandchild starts with the same recipe and adds a personal twist.


class Animal {
  String name;
  Animal(this.name);

  void eat() {
    print('$name is eating');
  }
}

class Dog extends Animal {
  Dog(String name) : super(name);

  void bark() {
    print('$name says woof');
  }
}

        Animal
       ┌──────────┐
       │ name     │
       │ eat()    │
       └────┬─────┘
            │ extends
       ┌────┴─────┐
       │   Dog    │
       │ bark()   │
       └──────────┘

A Dog object calls both eat() and bark().

The super Keyword

The word super points to the parent class. The constructor call super(name) passes data upward. Inside a method, super.eat() runs the parent version.

Overriding Methods

A child class replaces a parent method by writing the same name with the @override annotation.


class Cat extends Animal {
  Cat(String name) : super(name);

  @override
  void eat() {
    print('$name nibbles slowly');
  }
}

The annotation asks Dart to verify that the parent really has that method. A typo in the name triggers an error instead of a silent bug.

Abstract Classes

An abstract class describes a promise without full details. Nobody creates an object from it directly. Child classes must fill in the missing parts.


abstract class Shape {
  double area();
}

class Square extends Shape {
  double side;
  Square(this.side);

  @override
  double area() {
    return side * side;
  }
}

Flutter's StatelessWidget follows this pattern: it demands a build method from every child.

Interfaces with implements

Every Dart class doubles as an interface. The implements keyword demands that a class supplies every member of another class, with no code borrowed.


class Printer {
  void printDoc() {}
}

class OfficePrinter implements Printer {
  @override
  void printDoc() {
    print('Printing...');
  }
}

A class extends only one parent but implements many interfaces.

Mixins

A mixin packages reusable behavior that any class can attach. Picture clip-on accessories: a bike, a scooter, and a skateboard can all clip on the same bell.


mixin Swimmer {
  void swim() {
    print('Swimming');
  }
}

mixin Flyer {
  void fly() {
    print('Flying');
  }
}

class Duck extends Animal with Swimmer, Flyer {
  Duck(String name) : super(name);
}

   Animal      Swimmer     Flyer
      \           |         /
       \          |        /
        └────── Duck ─────┘

A Duck object eats, swims, and flies without duplicated code.

Restricting a Mixin with on

The on keyword limits a mixin to classes of a certain type.


mixin Trainable on Animal {
  void learnTrick() {
    print('$name learns a trick');
  }
}

Mixins in Flutter

Animation code uses SingleTickerProviderStateMixin to give a State class a timer that fires on every screen refresh:


class _BoxState extends State<Box> with SingleTickerProviderStateMixin {
  // animation code goes here
}

Choosing the Right Tool

KeywordGives YouLimit
extendsCode and data from a parentOne parent only
implementsA required list of membersNo code is copied
withReusable behaviorMany mixins allowed

Use extends for a true "is a" relationship, such as Dog is an Animal. Use a mixin for a shared ability, such as swimming.

Real-World Thinking

Imagine a delivery app with bikes, cars, and drones. Each vehicle has a name and a speed, so a parent class named Vehicle stores those shared properties. Each child adds its own details: a bike has pedals, a drone has a battery. Writing shared code once means a bug fix lands in a single place instead of three.

Mixins fit abilities that cut across the family tree. A drone and a delivery robot both carry a GpsTracker ability, although they share no parent. A mixin lets both classes attach the tracker without forcing an awkward family relationship.

Practice Ideas

Create an abstract class named Employee with an abstract salary() method. Write two children, FullTimeEmployee and Contractor, that calculate pay differently. Add a Reportable mixin that prints a one-line summary and attach it to both classes. Run the program and watch the shared behavior appear without repeated code.