Menu
Coddy logo textTech

Mixin vs. Vererbung

Teil des Abschnitts Objektorientierte Programmierung der Dart-Journey von Coddy — Lektion 54 von 110.

Nachdem Sie nun gelernt haben, wie Mixins funktionieren, lassen Sie uns klären, wann man sie anstelle von Vererbung einsetzt. Der entscheidende Unterschied liegt in der Beziehung, die sie ausdrücken.

Vererbung stellt eine „is-a“-Beziehung dar. Ein Dog ist ein Animal. Die Unterklasse ist eine spezialisierte Version der Elternklasse, und man kann nur eine Klasse erweitern.

Mixins hingegen stellen eine „Kann-Beziehung“ dar. Ein Dog kann schwimmen, aber Schwimmen ist nicht das, was einen Hund definiert.

// Vererbung: Dog IST ein Animal
class Animal {
  String name;
  Animal(this.name);
}

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

// Mixin: Dog KANN schwimmen (wird aber nicht durch Schwimmen definiert)
mixin Swimming {
  void swim() => print('Swimming');
}

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

Verwenden Sie Vererbung, wenn Klassen eine grundlegende Identität teilen und Sie Konstruktoren in der Elternklasse benötigen. Verwenden Sie Mixins, wenn Sie Klassen Funktionen hinzufügen möchten, die keinen gemeinsamen Vorfahren haben.

MerkmalVererbungMixin
Beziehungis-acan-do
BeschränkungNur ein ElternteilMehrere Mixins
KonstruktorenErlaubtNicht erlaubt
AnwendungsfallSpezialisierungGemeinsames Verhalten

Das Beste daran? Sie können beides kombinieren – eine Klasse erweitern und mehrere Funktionen einmischen, wodurch Ihre Klassen genau die Features erhalten, die sie benötigen.

challenge icon

Aufgabe

Einfach

Lassen Sie uns ein Arbeitersystem aufbauen, das demonstriert, wann Vererbung gegenüber Mixins verwendet werden sollte. Sie werden eine Basisklasse für die "is-a"-Beziehung (ist-ein) und Mixins für "can-do"-Fähigkeiten (kann-etwas) erstellen und diese dann kombinieren, um zu zeigen, wie beide Ansätze zusammenarbeiten.

Sie werden Ihren Code in drei Dateien organisieren:

  • worker.dart: Definieren Sie Ihre Basisklasse, die die Kernidentität aller Arbeiter festlegt:
    • Eine Worker-Klasse mit den Eigenschaften String name und String department. Fügen Sie einen Konstruktor hinzu, der beide Werte entgegennimmt. Fügen Sie eine Methode introduce() hinzu, die [name] works in [department] ausgibt.
  • skills.dart: Definieren Sie Mixins, die Fähigkeiten repräsentieren, die Arbeiter haben können (die "can-do"-Beziehungen):
    • Ein CanCode-Mixin mit einer Methode writeCode(), die Writing code... ausgibt.
    • Ein CanDesign-Mixin mit einer Methode createDesign(), die Creating design... ausgibt.
    • Ein CanManage-Mixin mit einer Methode leadTeam(), die Leading the team... ausgibt.
  • main.dart: Importieren Sie beide Dateien und erstellen Sie spezialisierte Arbeitertypen, die Vererbung mit Mixins kombinieren:
    • Eine Developer-Klasse, die Worker erweitert und das CanCode-Mixin verwendet.
    • Eine TechLead-Klasse, die Worker erweitert und sowohl das CanCode- als auch das CanManage-Mixin verwendet.
    • Erstellen Sie einen Developer namens 'Alice' in der Abteilung 'Engineering'.
    • Erstellen Sie einen TechLead namens 'Bob' in der Abteilung 'Engineering'.
    • Für Alice: Rufen Sie introduce() und dann writeCode() auf.
    • Geben Sie eine Leerzeile aus.
    • Für Bob: Rufen Sie introduce(), dann writeCode() und schließlich leadTeam() auf.

Beachten Sie, wie sowohl Developer als auch TechLead Arbeiter sind (Vererbung), aber unterschiedliche Dinge tun können (Mixins). Der TechLead kombiniert mehrere Fähigkeiten, ohne Mehrfachvererbung zu benötigen.

Erwartete Ausgabe:

Alice works in Engineering
Writing code...

Bob works in Engineering
Writing code...
Leading the team...

Spickzettel

Vererbung stellt eine „ist-ein“-Beziehung dar (eine Unterklasse ist eine spezialisierte Version der Elternklasse), während Mixins eine „kann-etwas“-Beziehung darstellen (Hinzufügen von Fähigkeiten, ohne die Identität zu definieren).

// Inheritance: Dog IS an Animal
class Animal {
  String name;
  Animal(this.name);
}

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

// Mixin: Dog CAN swim
mixin Swimming {
  void swim() => print('Swimming');
}

class Dog extends Animal with Swimming {
  Dog(String name) : super(name);
}
MerkmalVererbungMixin
Beziehungist-einkann-etwas
LimitNur ein ElternteilMehrere Mixins
KonstruktorenErlaubtNicht erlaubt
AnwendungsfallSpezialisierungGemeinsames Verhalten

Sie können beide Ansätze kombinieren – eine Klasse erweitern und mehrere Fähigkeiten einmischen:

class TechLead extends Worker with CanCode, CanManage {
  TechLead(String name, String department) : super(name, department);
}

Probier es selbst

import 'worker.dart';
import 'skills.dart';

// TODO: Erstelle eine Developer-Klasse, die Worker erweitert und das CanCode-Mixin verwendet

// TODO: Erstelle eine TechLead-Klasse, die Worker erweitert und sowohl CanCode- als auch CanManage-Mixins verwendet

void main() {
  // TODO: Erstelle einen Developer namens 'Alice' in der Abteilung 'Engineering'
  
  // TODO: Rufe introduce() und dann writeCode() für Alice auf
  
  // TODO: Gib eine Leerzeile aus
  
  // TODO: Erstelle einen TechLead namens 'Bob' in der Abteilung 'Engineering'
  
  // TODO: Rufe introduce(), writeCode() und dann leadTeam() für Bob auf
}
quiz iconTeste dich selbst

Diese Lektion enthält ein kurzes Quiz. Starte die Lektion, um es zu beantworten und deinen Fortschritt zu speichern.

Alle Lektionen in Objektorientierte Programmierung