100% Free Forever
AI-Powered Learning
Industry Expert Content
Certificates & Badges
Learn At Your Own Pace
Programming

Inheritance and Mixins

Learn how Dart classes share and extend behavior through single inheritance with extends and flexible code reuse through mixins with the with keyword.

Collections & OOPIntermediate10 min readJul 10, 2026
Analogies

Inheritance and Mixins

Inheritance lets one class, the subclass, acquire the fields and methods of another, the superclass, expressing an is-a relationship using the extends keyword. Dart supports only single inheritance, one extends per class, but layers in mixins for flexible, multi-source code reuse alongside it.

🏏

Cricket analogy: Just as an Allrounder is-a Batsman who can also bowl, in Dart class Allrounder extends Batsman inherits every field and method Batsman has while adding bowling-specific behavior on top.

Extending a Class

A subclass constructor uses super(...) in its initializer list to forward arguments to the superclass constructor, letting the superclass initialize the fields it owns before the subclass adds its own. This keeps field initialization logic in one place rather than duplicating it across every subclass.

🏏

Cricket analogy: class Allrounder extends Batsman with a constructor Allrounder(String name, int runs, this.wicketsTaken) : super(name, runs) uses super(name, runs) to delegate initialization of inherited fields to Batsman's own constructor.

dart
class Batsman {
  String name;
  int runs;
  Batsman(this.name, this.runs);

  void celebrate() => print('$name raises the bat');
}

class Allrounder extends Batsman {
  int wicketsTaken;
  Allrounder(String name, int runs, this.wicketsTaken) : super(name, runs);

  @override
  void celebrate() {
    print('$name does a bat-and-ball celebration');
  }
}

void main() {
  Batsman player = Allrounder('Ravindra Jadeja', 40, 3);
  player.celebrate(); // "Ravindra Jadeja does a bat-and-ball celebration"
}

Overriding Methods with @override

Marking a method with @override signals that it replaces the superclass's implementation, and Dart checks the signature matches at compile time. Because Dart uses dynamic dispatch, the overridden method that actually runs is chosen based on the object's real runtime type, even if it's referenced through a superclass-typed variable.

🏏

Cricket analogy: Overriding void celebrate() in Allrounder to print a bat-and-ball celebration replaces Batsman's simpler celebration, and calling celebrate() on an Allrounder object always runs the overridden version, even through a Batsman-typed reference.

Dart uses dynamic dispatch: even though player above is typed as Batsman, calling celebrate() runs Allrounder's overridden version at runtime because the actual object is an Allrounder. This is the essence of polymorphism.

Mixins with the with Keyword

A mixin, declared with the mixin keyword, packages reusable methods and fields that can be applied to any compatible class using with, without establishing a strict inheritance hierarchy. A class can extend only one superclass but can mix in several mixins at once, making mixins ideal for sharing unrelated capabilities.

🏏

Cricket analogy: A mixin like FieldingSkills that adds a takeCatch() method can be applied with class Allrounder extends Batsman with FieldingSkills, giving the class fielding behavior without needing a full Batsman-Bowler-Fielder inheritance chain.

dart
mixin FieldingSkills {
  void takeCatch() => print('Sharp catch taken!');
}

mixin Streamable {
  void goLive() => print('Now streaming live...');
}

class Allrounder extends Batsman with FieldingSkills, Streamable {
  Allrounder(String name, int runs) : super(name, runs);
}

void main() {
  var jadeja = Allrounder('Ravindra Jadeja', 40);
  jadeja.takeCatch(); // from FieldingSkills
  jadeja.goLive();    // from Streamable
}

Dart resolves multiple mixins right-to-left in the with clause for method conflicts; the last mixin listed wins if two mixins define the same method. Also, a class can only extend one superclass (single inheritance), but it can mix in many mixins, so use mixins for shared, unrelated behavior rather than trying to simulate multiple inheritance through extends.

  • Inheritance (extends) creates an is-a relationship where a subclass automatically gets all fields and methods of its superclass.
  • super(...) in a subclass's initializer list delegates initialization of inherited fields to the superclass's constructor.
  • @override marks a method that replaces the superclass's implementation, and Dart checks at compile time that the signature matches.
  • Dynamic dispatch means the overridden method that actually runs is determined by the object's real runtime type, not its declared variable type.
  • Mixins (declared with the mixin keyword, applied with with) let you share behavior across unrelated class hierarchies without single-inheritance constraints.
  • A class can extend only one superclass but can apply multiple mixins in a single with clause.
  • When multiple mixins define the same method, the rightmost mixin in the with clause takes precedence.

Practice what you learned

Was this page helpful?

Topics covered

#Programming#DartStudyNotes#InheritanceAndMixins#Inheritance#Mixins#Extending#Class#OOP#StudyNotes#SkillVeris