Abstrakte Methoden
Teil des Abschnitts Objektorientierte Programmierung der Dart-Journey von Coddy. Lektion 44 von 110.
Eine abstrakte Methode ist eine Methode, die innerhalb einer abstrakten Klasse deklariert wird und keinen Rumpf hat. Sie definiert die Methodensignatur, überlässt die Implementierung jedoch jeder Unterklasse. Jede Klasse, die die abstrakte Klasse erweitert, muss alle abstrakten Methoden überschreiben, andernfalls ist sie ebenfalls abstrakt.
abstract class Animal {
// Abstrakte Methode - kein Rumpf, muss von Unterklassen implementiert werden
String makeSound();
// Konkrete Methode - hat einen Rumpf, wird von allen Unterklassen geteilt
void breathe() {
print('Breathing...');
}
}
class Dog extends Animal {
@override
String makeSound() {
return 'Woof!'; // Muss Implementierung bereitstellen
}
}
class Cat extends Animal {
@override
String makeSound() {
return 'Meow!'; // Unterschiedliche Implementierung, gleiche Signatur
}
}Wenn eine Unterklasse vergisst, eine abstrakte Methode zu implementieren, gibt Dart einen Kompilierfehler aus. Das ist der entscheidende Punkt – abstrakte Methoden erzwingen einen Vertrag. Jede Unterklasse hat diese Methode garantiert, sodass Sie sie sicher auf jeder Instanz des abstrakten Typs aufrufen können.
// Du kannst den abstrakten Typ als Variablentyp verwenden
Animal a = Dog();
print(a.makeSound()); // Wuff!
Animal b = Cat();
print(b.makeSound()); // Miau!Abstrakte Methoden unterscheiden sich von konkreten Methoden in einer abstrakten Klasse. Konkrete Methoden haben einen Rumpf und werden unverändert vererbt. Abstrakte Methoden haben keinen Rumpf und müssen überschrieben werden.
Sie können beides in derselben abstrakten Klasse mischen, um ein bestimmtes Verhalten zu teilen, während Sie Unterklassen zwingen, ihr eigenes Verhalten für andere zu definieren.
| Merkmal | Abstrakte Methode | Konkrete Methode |
|---|---|---|
| Hat einen Rumpf | Nein | Ja |
| Muss überschrieben werden | Ja | Nein |
| Zweck | Vertrag erzwingen | Verhalten teilen |
| Wo | Nur in abstrakten Klassen | In jeder Klasse |
Aufgabe
EinfachErstellen wir einen Formrechner, der abstrakte Methoden in Aktion demonstriert. Du definierst eine abstrakte Klasse mit abstrakten Methoden, die jede Form unterschiedlich implementieren muss, und verwendest diese Formen anschließend über eine gemeinsame Schnittstelle.
Du organisierst deinen Code in vier Dateien:
shape.dart: Definiere eine abstrakte KlasseShapemit einemfinal-Feldcolor(String) und einem Konstruktor, der es initialisiert. Deklariere zwei abstrakte Methoden:double area()unddouble perimeter(). Füge außerdem eine konkrete Methodedescribe()hinzu, dieA [color] shape with area: [area] and perimeter: [perimeter]ausgibt. Daarea()undperimeter()abstrakt sind, stellt jede Unterklasse ihre eigene Berechnung bereit, aberdescribe()funktioniert für alle, ohne überschrieben werden zu müssen.circle.dart: Erstelle eine KlasseCircle, dieShapeerweitert. Sie besitzt einfinal-Feldradius(double). Ihr Konstruktor übernimmtcolorundradiusund übergibtcoloransuper. Implementierearea()so, dass3.14 * radius * radiuszurückgegeben wird, undperimeter()so, dass2 * 3.14 * radiuszurückgegeben wird.rectangle.dart: Erstelle eine KlasseRectangle, dieShapeerweitert. Sie besitzt diefinal-Felderwidthundheight(beide double). Ihr Konstruktor übernimmtcolor,widthundheightund übergibtcoloransuper. Implementierearea()so, dasswidth * heightzurückgegeben wird, undperimeter()so, dass2 * (width + height)zurückgegeben wird.main.dart: Importiere alle Dateien. Erstelle einenCirclemit der Farbe'red'und dem Radius5.0sowie einRectanglemit der Farbe'blue', der Breite4.0und der Höhe6.0. Rufe für jede Formdescribe()auf. Erstelle anschließend eineList<Shape>, die beide Formen enthält, durchlaufe die Liste und gib für jede FormArea: [area]aus.
Erwartete Ausgabe:
A red shape with area: 78.5 and perimeter: 31.400000000000002
A blue shape with area: 24.0 and perimeter: 20.0
Area: 78.5
Area: 24.0Probier es selbst
import 'shape.dart';
import 'circle.dart';
import 'rectangle.dart';
void main() {
// TODO: Erstelle einen Circle mit der Farbe 'red' und dem Radius 5.0
// TODO: Erstelle ein Rectangle mit der Farbe 'blue', der Breite 4.0 und der Höhe 6.0
// TODO: Rufe describe() für den circle auf
// TODO: Rufe describe() für das rectangle auf
// TODO: Erstelle eine List<Shape>, die beide Formen enthält
// TODO: Iteriere durch die Liste und gib "Area: [area]" für jede Form aus
}
Diese Lektion enthält ein kurzes Quiz. Starte die Lektion, um es zu beantworten und deinen Fortschritt zu speichern.
Alle Lektionen in Objektorientierte Programmierung
1Grundlagen der OOP
Externe DateienBibliotheken & ImportsEinführung in die OOPKlassen vs. ObjekteDas Schlüsselwort thisMethodenInstanzvariablenGrundlagen von KonstruktorenRückblick – Einfacher Taschenrechner4Null-Sicherheit
Einführung in die Null-SicherheitNullable vs. Non-NullableDie Operatoren ? und !Late-Schlüsselwort und Null-SicherheitNull-bewusste OperatorenNull-Sicherheit in KlassenRückblick – Benutzers профilsystem7Abstrakte Klassen & Interfaces
Abstrakte KlassenAbstrakte MethodenInterfaces in DartImplizite InterfacesImplementieren vs. ErweiternMehrere InterfacesZusammenfassung – Formrechner10Collections & Generics
Übersicht über List, Set und MapTypsichere CollectionsGenerische KlassenGenerische MethodenGenerische EinschränkungenIterable & IteratorRückblick – Generischer Speicher13Fortgeschrittene OOP-Konzepte
Komposition vs. VererbungErweiterungsmethodenAufrufbare KlassenVersiegelte Klassen (Dart 3)Records (Dart 3)Muster & Matching (3.0)Enums mit Methoden16Projekt: Bibliotheksverwaltung
ProjektübersichtBuch- und Benutzerklassen2Konstruktoren in Dart
StandardkonstruktorBenannte KonstruktorenInitialisierungslistenKonstantenkonstruktorenFactory-KonstruktorenWeiterleitende KonstruktorenRückblick – Shape Builder5Kapselung
Öffentliche vs. private MemberDie _-Präfix-KonventionBibliotheksweite SichtbarkeitTiefergehende Getter & SetterInformationsverbergungRückblick – Studierendendaten8Mixins
Einführung in MixinsMixins erstellenMehrere Mixins verwendenDas Schlüsselwort „on“ in MixinsMixin vs. VererbungMixin vs. SchnittstelleRückblick – Tiersystem11Spezielle Methoden
toString()-ÜberschreibunghashCode- & ==-ÜberschreibungComparable-Schnittstellecall()-MethodenoSuchMethod-ÜberschreibungWiederholung – Benutzerdefinierte Collection14Entwurfsmuster Teil 1
Einführung in EntwurfsmusterSingleton-MusterFabrikmusterBeobachtermusterStrategiemuster17Abschließende Herausforderungen
E-Learning-PlattformBankingsystemSpielcharaktersystemFahrzeugvermietung3Klassen-Eigenschaften
Instanz- vs. statische MemberFinal- und Const-FelderLate-VariablenStatische Methoden und FelderGetter und SetterRückblick – Bankkontoverwaltung6Vererbung
Grundlegende VererbungDas Schlüsselwort superMethodenüberschreibungDie Annotation @overrideDas Schlüsselwort final für KlassenKonstruktoren und VererbungZusammenfassung – Mitarbeiterhierarchie9Polymorphismus
Grundlagen des PolymorphismusPolymorphismus über InterfacesLaufzeit-TypüberprüfungDie Operatoren is & asCovariant-SchlüsselwortZusammenfassung – ZahlungsprozessorÜbe selbstständig: Online-Dart-Compiler