Callable Classes
Teil des Abschnitts Objektorientierte Programmierung der Dart-Journey von Coddy — Lektion 84 von 110.
In Dart können Sie Instanzen einer Klasse wie Funktionen aufrufbar machen, indem Sie die call()-Methode implementieren. Dies ermöglicht es Ihnen, ein Objekt mit der Funktionsaufrufsyntax zu verwenden – also Klammern direkt auf der Instanz anzuwenden.
class Multiplier {
final int factor;
Multiplier(this.factor);
int call(int value) {
return value * factor;
}
}
void main() {
var double = Multiplier(2);
var triple = Multiplier(3);
print(double(5)); // 10 - das Objekt wie eine Funktion aufrufen
print(triple(5)); // 15
}Wenn Sie double(5) schreiben, ruft Dart automatisch die call()-Methode mit 5 als Argument auf. Das Objekt verhält sich wie eine Funktion, während es gleichzeitig seinen Zustand (das factor-Feld) beibehält.
Die call()-Methode kann jede beliebige Signatur haben – mehrere Parameter, optionale Parameter oder sogar verschiedene Typen zurückgeben:
class Greeter {
final String greeting;
Greeter(this.greeting);
String call(String name, {String punctuation = '!'}) {
return '$greeting, $name$punctuation';
}
}
void main() {
var hello = Greeter('Hello');
print(hello('Alice')); // Hallo, Alice!
print(hello('Bob', punctuation: '.')); // Hallo, Bob.
}Aufrufbare Klassen sind nützlich, wenn Sie funktionsähnliches Verhalten in Kombination mit Zustand oder Konfiguration benötigen. Sie werden häufig zur Erstellung von wiederverwendbaren Operationen, Validatoren oder Transformationen verwendet, die sich Einstellungen zwischen den Aufrufen merken müssen.
Aufgabe
EinfachLassen Sie uns ein Textformatierungssystem mit aufrufbaren Klassen (callable classes) erstellen! Sie werden Objekte erstellen, die wie Funktionen aufgerufen werden können, um Text auf verschiedene Weise zu transformieren, während sie ihre eigenen Konfigurationseinstellungen beibehalten.
Sie werden Ihren Code in zwei Dateien organisieren:
formatters.dart: Erstellen Sie zwei aufrufbare Klassen, die Text transformieren:- Eine
Wrapper-Klasse, die Text mit einem Präfix und einem Suffix umschließt. Sie sollte einenString prefixund einenString suffixspeichern und, wenn sie mit einemString text-Parameter aufgerufen wird, den zwischen Präfix und Suffix eingeschlossenen Text zurückgeben. - Eine
Repeater-Klasse, die Text eine bestimmte Anzahl von Malen wiederholt. Sie sollte einenint times-Wert speichern und, wenn sie mit einemString text-Parameter aufgerufen wird, den Text so oft wiederholt zurückgeben, mit einem Leerzeichen zwischen jeder Wiederholung.
- Eine
main.dart: Importieren Sie Ihre Formatierer und demonstrieren Sie, wie aufrufbare Klassen funktionieren:- Erstellen Sie einen
Wrappermit dem Präfix"["und dem Suffix"]" - Erstellen Sie einen weiteren
Wrappermit dem Präfix"***"und dem Suffix"***" - Erstellen Sie einen
Repeater, der 3 Mal wiederholt - Rufen Sie den ersten Wrapper mit
"Hello"auf und geben Sie das Ergebnis aus - Rufen Sie den zweiten Wrapper mit
"Important"auf und geben Sie das Ergebnis aus - Rufen Sie den Repeater mit
"Go"auf und geben Sie das Ergebnis aus - Kombinieren Sie sie schließlich: Rufen Sie den ersten Wrapper mit dem Ergebnis des Aufrufs des Repeaters mit
"Dart"auf und geben Sie das Ergebnis aus
- Erstellen Sie einen
Beachten Sie, wie sich jedes Formatierer-Objekt an seine Konfiguration erinnert und direkt mit Klammern aufgerufen werden kann, genau wie eine Funktion!
Erwartete Ausgabe:
[Hello]
***Important***
Go Go Go
[Dart Dart Dart]Spickzettel
Klassen können wie Funktionen aufrufbar gemacht werden, indem die Methode call() implementiert wird:
class Multiplier {
final int factor;
Multiplier(this.factor);
int call(int value) {
return value * factor;
}
}
void main() {
var double = Multiplier(2);
print(double(5)); // 10 - Aufruf des Objekts wie eine Funktion
}Die Methode call() kann jede beliebige Signatur mit mehreren Parametern, optionalen Parametern oder verschiedenen Rückgabetypen haben:
class Greeter {
final String greeting;
Greeter(this.greeting);
String call(String name, {String punctuation = '!'}) {
return '$greeting, $name$punctuation';
}
}
void main() {
var hello = Greeter('Hello');
print(hello('Alice')); // Hello, Alice!
print(hello('Bob', punctuation: '.')); // Hello, Bob.
}Aufrufbare Klassen sind nützlich, um funktionsähnliches Verhalten kombiniert mit Status oder Konfiguration zu erstellen.
Probier es selbst
import 'formatters.dart';
void main() {
// TODO: Erstelle einen Wrapper mit dem Präfix "[" und dem Suffix "]"
// TODO: Erstelle einen weiteren Wrapper mit dem Präfix "***" und dem Suffix "***"
// TODO: Erstelle einen Repeater, der 3-mal wiederholt
// TODO: Rufe den ersten Wrapper mit "Hello" auf und gib das Ergebnis aus
// TODO: Rufe den zweiten Wrapper mit "Important" auf und gib das Ergebnis aus
// TODO: Rufe den Repeater mit "Go" auf und gib das Ergebnis aus
// TODO: Kombiniere sie: Rufe den ersten Wrapper mit dem Ergebnis des
// Aufrufs des Repeaters mit "Dart" auf und gib das Ergebnis 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 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