Dart Interface und implements – Klassen um Fähigkeiten erweitern
Interfaces und implements – abstrakte Konzepte
Heute habe ich mich an fortgeschrittenere Dart-Themen gewagt: abstrakte Klassen und implements. Das Thema wirkte anfangs ziemlich abstrakt (abstract heißt ja auch genau das), wurde mir aber anhand von Beispielen klarer.
Live-Demo: abstrakte Klasse und implements
Lernen Sie den Einsatz von abstrakten Klassen und implements interaktiv:
Was ist eine abstrakte Klasse?
Eine abstrakte Klasse ist eine Klasse, von der Sie selbst kein Objekt erzeugen können, die aber eine Vorlage für andere Klassen liefert. Stellen Sie es sich so vor: Sie haben ein Kochbuch, aber Sie können das Kochbuch nicht essen. Sie müssen erst nach dem Rezept kochen.
abstract class Squeezable {
void howToSqueeze() {}
}
abstract class Eatable {
void howToEat() {}
}Hier habe ich zwei abstrakte Klassen definiert: eine für „auspressbare Dinge“, die andere für „essbare Dinge“.
Klassen mit implements erweitern
Anders als bei extends können Sie mit implements Fähigkeiten aus mehreren Klassen übernehmen. Ich nenne das „einen Vertrag unterschreiben“. Sie versprechen: „Ich werde diese Fähigkeiten umsetzen.“
Beispiel Apfel
abstract class Squeezable {
void howToSqueeze() {}
}
abstract class Eatable {
void howToEat() {}
}
class Apple implements Eatable, Squeezable {
@override
void howToEat() {
print("Bite with your mouth and chew");
}
@override
void howToSqueeze() {
print("Put in juicer and squeeze");
}
}
void main() {
var apple1 = Apple();
print("How to eat an apple?");
apple1.howToEat();
print("\nHow to squeeze an apple?");
apple1.howToSqueeze();
}Ausgabe:
How to eat an apple?
Bite with your mouth and chew
How to squeeze an apple?
Put in juicer and squeezeWarum zwei Interfaces?
Weil Sie einen Apfel sowohl essen als auch zu Saft auspressen können. Denken Sie dagegen an einen Stein: Ein Stein ist nicht essbar, vielleicht aber zerbrechbar. Dann würde die Klasse Stone nur das Interface Breakable implementieren.
Der Unterschied zwischen extends und implements
Anfangs habe ich die beiden verwechselt, inzwischen ist es klar:
| Extends | Implements |
|---|---|
| Erbt von genau einer Klasse | Kann mehrere Interfaces übernehmen |
| Erbt die Fähigkeiten der Elternklasse | Muss den Vertrag erfüllen |
| Überschreiben ist optional | Überschreiben ist Pflicht |
Erläuterung am Beispiel
// EXTENDS example
class Animal {
void breathe() {
print("Breathing");
}
}
class Dog extends Animal {
// We automatically got the breathe method
// We can override if we want, or not
}
// IMPLEMENTS example
abstract class Walkable {
void walk();
}
class Human implements Walkable {
@override
void walk() {
// We MUST write this
print("Human is walking");
}
}Beispiel aus der Flutter-Praxis
Tatsächlich nutzen wir diese Struktur ständig, wenn wir in Flutter Widgets schreiben:
abstract class Clickable {
void whenClicked();
}
abstract class Scrollable {
void whenScrolled();
}
class CustomButton implements Clickable {
@override
void whenClicked() {
print("Button clicked!");
// Send to analytics
// Start animation
// Save data etc.
}
}
class CustomListView implements Clickable, Scrollable {
@override
void whenClicked() {
print("List item clicked");
}
@override
void whenScrolled() {
print("List scrolled");
}
}Wie Sie sehen, kann CustomListView sowohl angeklickt als auch gescrollt werden. Hätten wir extends verwendet, hätten wir nur die Fähigkeiten einer einzigen Klasse übernehmen können.
Unterstützung durch die IDE
In VS Code oder Android Studio ergänzt die IDE die Methoden automatisch, sobald Sie ein Interface implementieren. Das ist sehr praktisch:
- Sie schreiben
implements Eatable - Eine rote Linie erscheint (es liegt ein Fehler vor)
- Sie klicken auf das Glühbirnen-Symbol
- Sie wählen „Implement members“
- Alle Methoden werden automatisch ergänzt!
Kann ich ungenutzte Methoden löschen?
Technisch nicht, denn implements ist ein Vertrag. Sie können sie aber leer lassen:
class Orange implements Eatable, Squeezable {
@override
void howToEat() {
print("Peel and eat");
}
@override
void howToSqueeze() {
// Left empty, but we had to write it
}
}Oder besser: Wenn Sie es wirklich nicht brauchen, implementieren Sie dieses Interface gar nicht erst.
Was habe ich heute gelernt?
- Abstrakte Klassen dienen als Vorlage
- Implements erlaubt uns, mehrere Interfaces zu nutzen
- Ich habe den Unterschied zwischen extends und implements verstanden
- Die Autovervollständigung der IDE ist sehr hilfreich
Morgen sehe ich mir Collections an (List, Set, Map). Auch die sind in Flutter sehr wichtig.
Ein verwirrender Punkt
Sie können eine abstrakte Klasse sowohl erweitern als auch implementieren. Der Unterschied:
- Bei extends: Sie können die enthaltenen Methoden nutzen (Überschreiben ist optional)
- Bei implements: Sie müssen alles überschreiben
abstract class Shape {
void draw() {
print("Drawing shape");
}
}
// With extends
class Square extends Shape {
// We can use the draw() method, override is optional
}
// With implements
class Circle implements Shape {
@override
void draw() {
// We MUST write this
print("Drawing circle");
}
}Ich habe eine Weile gebraucht, um dieses Detail zu verstehen, aber jetzt ist es klar.
Wenn Sie mit mir arbeiten möchten:
Bis zum nächsten Beitrag!