Generische Methoden
Teil des Abschnitts Objektorientierte Programmierung der Dart-Journey von Coddy — Lektion 66 von 110.
Genauso wie Klassen generisch sein können, können auch einzelne Methoden ihre eigenen Typparameter haben. Dies ist nützlich, wenn Sie eine flexible Methode benötigen, ohne die gesamte Klasse generisch zu machen.
Eine generische Methode deklariert ihren Typparameter vor dem Rückgabetyp:
T findFirst<T>(List<T> items) {
return items.first;
}
void main() {
var firstNumber = findFirst<int>([1, 2, 3]);
var firstWord = findFirst<String>(['hello', 'world']);
print(firstNumber); // 1
print(firstWord); // hello
}Dart kann den Typ oft aus den Argumenten ableiten, sodass Sie ihn nicht immer explizit angeben müssen:
var result = findFirst([10, 20, 30]); // Dart leitet int abGenerische Methoden sind besonders nützlich innerhalb von Klassen, wenn nur bestimmte Operationen Typflexibilität benötigen:
class Printer {
void printItem<T>(T item) {
print('Printing: $item');
}
List<T> duplicate<T>(T item, int count) {
return List.filled(count, item);
}
}
void main() {
var printer = Printer();
printer.printItem<String>('Hello');
printer.printItem(42); // Typ wird als int abgeleitet
var copies = printer.duplicate('Hi', 3);
print(copies); // [Hi, Hi, Hi]
}Generische Methoden bieten Ihnen eine feingranulare Kontrolle über die Typsicherheit auf Methodenebene, wodurch Ihre Klassen einfacher bleiben, während Sie dennoch von der Typprüfung zur Kompilierzeit profitieren.
Aufgabe
EinfachLassen Sie uns ein Dienstprogramm zur Datentransformation erstellen, das die Leistungsfähigkeit generischer Methoden demonstriert. Sie werden eine Transformer-Klasse mit Methoden erstellen, die mit jedem Typ arbeiten können, was Ihnen Flexibilität bietet, ohne die gesamte Klasse generisch zu machen.
Sie werden Ihren Code in zwei Dateien organisieren:
transformer.dart: Erstellen Sie eineTransformer-Klasse mit diesen generischen Methoden:T getFirst<T>(List<T> items)- gibt das erste Element aus einer Liste zurückT getLast<T>(List<T> items)- gibt das letzte Element aus einer Liste zurückList<T> repeat<T>(T item, int times)- erstellt eine Liste, die das Element in der angegebenen Anzahl von Wiederholungen enthältvoid printPair<A, B>(A first, B second)- gibt zwei Werte im FormatPair: [first] and [second]aus
main.dart: Importieren Sie Ihre Transformer-Datei und demonstrieren Sie jede generische Methode mit verschiedenen Typen:- Erstellen Sie eine
Transformer-Instanz - Verwenden Sie
getFirstfür[10, 20, 30]und geben Sie das Ergebnis aus - Verwenden Sie
getFirstfür['apple', 'banana', 'cherry']und geben Sie das Ergebnis aus - Verwenden Sie
getLastfür[1.5, 2.5, 3.5]und geben Sie das Ergebnis aus - Verwenden Sie
repeat, um eine Liste von'Hi'zu erstellen, die4Mal wiederholt wird, und geben Sie das Ergebnis aus - Verwenden Sie
repeat, um eine Liste von7zu erstellen, die3Mal wiederholt wird, und geben Sie das Ergebnis aus - Verwenden Sie
printPairmit'Name'und42 - Verwenden Sie
printPairmit100undtrue
- Erstellen Sie eine
Beachten Sie, wie jede Methode ihre eigenen Typparameter deklariert, sodass dasselbe Transformer-Objekt mit Integern, Strings, Doubles und Booleans arbeiten kann – und das bei voller Typsicherheit. Die Methode printPair demonstriert die Verwendung von zwei Typparametern in einer einzigen Methode.
Erwartete Ausgabe:
10
apple
3.5
[Hi, Hi, Hi, Hi]
[7, 7, 7]
Pair: Name and 42
Pair: 100 and trueSpickzettel
Generische Methoden deklarieren Typparameter vor dem Rückgabetyp, wodurch einzelne Methoden flexibel sein können, ohne dass die gesamte Klasse generisch sein muss:
T findFirst<T>(List<T> items) {
return items.first;
}Dart kann den Typ aus den Argumenten ableiten, daher ist die explizite Typangabe optional:
var result = findFirst([10, 20, 30]); // Dart leitet int abGenerische Methoden können innerhalb nicht-generischer Klassen verwendet werden:
class Printer {
void printItem<T>(T item) {
print('Printing: $item');
}
List<T> duplicate<T>(T item, int count) {
return List.filled(count, item);
}
}Methoden können mehrere Typparameter deklarieren:
void printPair<A, B>(A first, B second) {
print('Pair: $first and $second');
}Probier es selbst
import 'transformer.dart';
void main() {
// Erstelle eine Transformer-Instanz
var transformer = Transformer();
// TODO: Verwende getFirst für [10, 20, 30] und gib das Ergebnis aus
// TODO: Verwende getFirst für ['apple', 'banana', 'cherry'] und gib das Ergebnis aus
// TODO: Verwende getLast für [1.5, 2.5, 3.5] und gib das Ergebnis aus
// TODO: Verwende repeat, um eine Liste von 'Hi' 4-mal wiederholt zu erstellen und gib sie aus
// TODO: Verwende repeat, um eine Liste von 7 3-mal wiederholt zu erstellen und gib sie aus
// TODO: Verwende printPair mit 'Name' und 42
// TODO: Verwende printPair mit 100 und true
}
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 this-SchlüsselwortMethodenInstanzvariablenKonstruktor-GrundlagenWiederholung – Einfacher Taschenrechner4Null-Sicherheit
Einführung in Null-SicherheitNullable vs. Non-NullableDie ? und ! OperatorenLate-Schlüsselwort & Null-SicherheitNull-aware OperatorenNull-Sicherheit in KlassenZusammenfassung – Benutzerprofil-System7Abstrakte Klassen & Interfaces
Abstrakte KlassenAbstrakte MethodenInterfaces in DartImplizite InterfacesImplementieren vs. ErweiternMehrfache InterfacesRückblick – Shape Calculator10Collections & Generics
Überblick über List, Set und MapTypsichere CollectionsGenerische KlassenGenerische MethodenGenerische ConstraintsIterable & IteratorZusammenfassung – Generische Speicherung13Fortgeschrittene OOP-Konzepte
Komposition vs. VererbungExtension MethodsCallable ClassesSealed Classes (Dart 3)Records (Dart 3)Patterns & Matching (3.0)Enums mit Methoden16Projekt: Bibliotheksverwaltung
ProjektübersichtBuch- und Benutzerklassen2Konstruktoren in Dart
Standard-KonstruktorBenannte KonstruktorenInitialisierungslistenKonstante KonstruktorenFactory-KonstruktorenWeiterleitende KonstruktorenZusammenfassung – Shape Builder5Kapselung
Öffentliche vs. private MemberDie _ Präfix-KonventionSichtbarkeit auf Library-EbeneGetter & Setter im DetailInformation HidingRückblick – Schülerdatensätze8Mixins
Einführung in MixinsMixins erstellenMehrere Mixins verwendenDas on-Schlüsselwort in MixinsMixin vs. VererbungMixin vs. InterfaceZusammenfassung - Tiersystem11Spezielle Methoden
toString() überschreibenhashCode & == überschreibenComparable-Interfacecall()-MethodenoSuchMethod überschreibenZusammenfassung – Eigene Collection14Entwurfsmuster Teil 1
Einführung in EntwurfsmusterSingleton-MusterFactory-MusterObserver-MusterStrategy-Muster3Klasseneigenschaften
Instanz- vs. statische MemberFinal & Const FelderLate-VariablenStatische Methoden & FelderGetter und SetterZusammenfassung – Bankkonto-Manager6Vererbung
Grundlagen der VererbungDas super-SchlüsselwortMethoden überschreibenDie @override-AnnotationDas final-Klassen-SchlüsselwortKonstruktoren & VererbungRückblick – Mitarbeiter-Hierarchie9Polymorphismus
Polymorphismus-GrundlagenPolymorphismus über InterfacesTypprüfung zur LaufzeitDie is & as OperatorenDas covariant SchlüsselwortZusammenfassung – Payment Processor