In Kotlin wird die Verhaltensdelegation durch das Sprachkonstrukt des Schlüsselworts by direkt in der Klassensignatur umgesetzt. Das ermöglicht die automatische Weiterleitung von Methodenaufrufen einer Schnittstelle (oder mehrerer Schnittstellen) an ein anderes Objekt mit der Implementierung, wodurch Boilerplate-Code reduziert und die Komposition erleichtert wird.
Das Aufkommen der Schnittstellendelegation ist ein Versuch, die Einschränkungen und Nachteile der Mehrfachvererbung zu beseitigen. Es ist die Idee "Komposition vor Vererbung" — wir delegieren Verhalten, ohne auf eine Klassenhierarchie zurückgreifen zu müssen. Entlehnt von Sprachen, in denen Komposition populärer ist (wie Go, Scala).
In Java und anderen Sprachen muss oft eine Schnittstelle erstellt und jeder Methode manuell implementiert werden, wobei die Logik an ein anderes Feld übergeben wird (Object Adapter Pattern), was schnell veraltet, wenn die Anzahl der Methoden zunimmt.
Kotlin ermöglicht die deklarative Delegation einer Schnittstelle mit by:
interface Logger { fun log(msg: String) } class ConsoleLogger: Logger { override fun log(msg: String) = println(msg) } class Service(logger: Logger): Logger by logger { fun doWork() { log("Arbeit begonnen") // ... } } val service = Service(ConsoleLogger()) service.doWork()
Wichtige Merkmale:
Was passiert, wenn in der Service-Klasse eine eigene Methode der Schnittstelle mit derselben Signatur hinzugefügt wird?
Die eigene Implementierung "überschreibt" die delegierte — das heißt, es hat Vorrang die Methode, die explizit in der Klasse definiert ist:
class Service(logger: Logger): Logger by logger { override fun log(msg: String) = println("PREFIX: $msg") }
Kann eine Klasse mehrere Schnittstellen an verschiedene Objekte delegieren?
Ja, eine Klasse kann mehrere Schnittstellen an verschiedene Objekte implementieren und delegieren, aber jede Schnittstelle wird an ein Objekt delegiert:
class Service( logger: Logger, tracker: Tracker ): Logger by logger, Tracker by tracker
Wie unterscheidet sich die Schnittstellendelegation von der Eigenschaftendelegation über by?
Die Klasse implementiert manuell die Schnittstelle, jeder Methode ruft den Delegaten auf, und bei der Hinzufügung neuer Methoden wird vergessen, die Proxierung zu aktualisieren, was zu Fehlern führt.
Vorteile:
Nachteile:
Es wird die sprachliche Delegation verwendet, nur nicht standardisierte Methoden werden innerhalb der Klasse implementiert, neue Funktionalitäten werden ohne größere Änderungen hinzugefügt.
Vorteile:
Nachteile: