Klasse erweitern Extend a class
Verwenden Sie das Schlüsselwort extends, um aus einer Oberklasse (Superklasse) eine Unterklasse (Subklasse) abzuleiten.
Mit dem Schlüsselwort super können Sie aus einer Unterklasse heraus Mitglieder der Oberklasse aufrufen (Methoden, Konstruktoren usw.).
class Television {
void turnOn() {
...
// Code, der in der Methode der Oberklasse ausgeführt wird
}
}
// SmartTelevision ist die Unterklasse, Television die Oberklasse
class SmartTelevision extends Television {
@override
void turnOn() {
super.turnOn(); // Aufruf der turnOn-Methode der Oberklasse
// Spezifischer Code für die Unterklasse
...
}
}Code-Sprache: Dart (dart)
Beispiel: Ein herkömmlicher Fernseher ist die Oberklasse, ein Smart-TV die Unterklasse. Der Smart-TV erbt alle Eigenschaften des normalen Fernsehers.
extends hat einen weiteren Anwendungsfall: In dem Kapitel zu Generika im Zusammenhang mit parametrisierten Typen.
Praktisches Beispiel
class Television {
void turnOn() {
print("Fernseher einschalten, grundlegende Bildausgabe starten");
}
}
// SmartTelevision ist die Unterklasse, Television die Oberklasse
class SmartTelevision extends Television {
@override
void turnOn() {
super.turnOn(); // Aufruf der turnOn-Methode der Oberklasse
// Spezifischer Code für die Unterklasse
print("Smart-TV: Netzwerkmodul aktivieren, Startbildschirm des Smart-Systems laden");
}
}
void main() {
// Instanz eines normalen Fernsehers
Television normalTv = Television();
print("===== Normaler Fernseher einschalten =====");
normalTv.turnOn();
// Instanz eines Smart-TVs
SmartTelevision smartTv = SmartTelevision();
print("\n===== Smart-TV einschalten =====");
smartTv.turnOn();
}Code-Sprache: Dart (dart)
Ausgabeergebnis
D:\dartdemo\firstdart>dart run
Building package executable... (1.4s)
Built firstdart:firstdart.
===== Normaler Fernseher einschalten =====
Fernseher einschalten, grundlegende Bildausgabe starten
===== Smart-TV einschalten =====
Fernseher einschalten, grundlegende Bildausgabe starten
Überschreiben von Mitgliedern Overriding members
1. Überschreibbare Elemente
Eine Unterklasse kann überschreiben: Instanzmethoden (auch Operatoren), Getter, Setter.
2. Die Annotation @override
Zweck: Explizit kennzeichnen, dass die Methode absichtlich ein Mitglied der Oberklasse überschreibt. Der Compiler unterstützt bei der Prüfung der Regeln.
class Television {
set contrast(int value) {}
}
class SmartTelevision extends Television {
@override // Teilt dem Compiler mit, dass diese Methode die Oberklassenmethode überschreibt
set contrast(num value) {}
}
Code-Sprache: JavaScript (javascript)
3. Regeln für gültiges Überschreiben
- Rückgabetyp: Der Rückgabetyp der überschreibenden Methode muss dem Typ der Oberklassenmethode entsprechen oder ein Untertyp davon sein.
- Parametertyp: Der Parametertyp der überschreibenden Methode muss dem Typ der Oberklasse entsprechen oder ein Obertyp sein. (Beispiel
int→num. num ist ein Obertyp von int und damit zulässig.) - Anzahl positionaler Parameter: Wenn die ursprüngliche Methode n positionale Parameter hat, muss die überschreibende Methode ebenfalls genau n positionale Parameter definieren.
- Generische Einschränkungen: Generische Methoden können keine nicht generischen Methoden überschreiben und umgekehrt.
4. Das Schlüsselwort covariant (Sonderfall für die Typverengung)
Die Standardregeln verbieten die Verengung von Parametertypen (ein Downcast kann zur Laufzeit Typfehler verursachen) ;
Wenn der Entwickler sicherstellen kann, dass keine Typfehler auftreten, markieren Sie den Parameter mit covariant, um eine Typverengung zu ermöglichen.
Wenn Sie den Operator == überschreiben, müssen Sie außerdem unbedingt den hashCode-Getter von Object überschreiben.
noSuchMethod ()
1. Funktion
Wenn Code versucht, eine nicht vorhandene Instanzmethode / Instanzvariable aufzurufen, können Sie noSuchMethod() überschreiben, um den Aufruf abzufangen und eigene Logik auszuführen.
Ohne Überschreiben wird beim Zugriff auf nicht vorhandene Mitglieder direkt ein NoSuchMethodError ausgelöst.
class A {
@override
void noSuchMethod(Invocation invocation) {
print('You tried to use a non-existent member: ${invocation.memberName}');
}
}
- Objekt
Invocation: Speichert alle Informationen zum Aufruf (Mitgliedsname, Parameter usw.)
2. Zwei Voraussetzungen zum Aufruf nicht implementierter Methoden (eine genügt)
- Der statische Typ des aufgerufenen Objekts ist
dynamic; - Der statische Typ des Empfängers deklariert die nicht implementierte Methode (kann abstrakt sein), und der dynamische Typ des Empfängers verfügt über eine andere
noSuchMethod()-Implementierung als die eingebaute Version vonObject.
Beispiel
class A {
@override
void noSuchMethod(Invocation invocation) {
print('You tried to use a non-existent member: ${invocation.memberName}');
// Zusätzliche Ausgabe von Aufrufparametern und Typ für vollständige Informationen
print('Aufrufparameter:${invocation.arguments}');
print('Aufruftyp:${invocation.runtimeType}');
}
}
void main() {
A obj = A();
// Aufruf nicht existierender Methode löst noSuchMethod aus
obj.hello("test", 123);
// Zugriff auf nicht vorhandene Eigenschaft
obj.unknownValue;
}
D:\dartdemo\firstdart>dart run
Building package executable...
Failed to build firstdart:firstdart:
bin/firstdart.dart:6:30: Error: The getter 'arguments' isn't defined for the type 'Invocation'.
- 'Invocation' is from 'dart:core'.
Try correcting the name to the name of an existing getter, or defining a getter or field named 'arguments'.
print('cal:${invocation.arguments}');
^^^^^^^^^
bin/firstdart.dart:14:7: Error: The method 'hello' isn't defined for the type 'A'.
- 'A' is from 'bin/firstdart.dart'.
Try correcting the name to the name of an existing method, or defining a method named 'hello'.
obj.hello("test", 123);
^^^^^
bin/firstdart.dart:16:7: Error: The getter 'unknownValue' isn't defined for the type 'A'.
- 'A' is from 'bin/firstdart.dart'.
Try correcting the name to the name of an existing getter, or defining a getter or field named 'unknownValue'.
obj.unknownValue;
Klassenvererbung und Überschreiben von Mitgliedern