In Kotlin is gedragdelegatie geïmplementeerd met behulp van het taalmechanisme van het sleutelwoord by, direct in de handtekening van de klasse. Dit stelt je in staat om automatisch methoden van een interface (of meerdere interfaces) naar een andere objectimplementatie door te geven, waardoor boilerplate-code vermindert en compositie wordt vergemakkelijkt.
De opkomst van interfacedelegatie is een poging om de beperkingen en tekortkomingen van meervoudige overerving te verhelpen. Dit is het idee van "compositie boven overerving" — je delegeert gedrag zonder een klassenhiërarchie te creëren. Geleend uit talen waar compositie populairder is (bijvoorbeeld Go, Scala).
In Java en andere talen moet je vaak een interface maken en handmatig elke methode implementeren, waarbij je de logica naar een ander veld doorgeeft (Object Adapter-patroon), wat snel verouderd raakt naarmate het aantal methoden toeneemt.
Kotlin maakt het mogelijk om declaratief een interface te delegeren met behulp van 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("Werk gestart") // ... } } val service = Service(ConsoleLogger()) service.doWork()
Belangrijke eigenschappen:
Wat gebeurt er als je in de klasse Service je eigen methode van de interface met dezelfde handtekening toevoegt?
De eigen implementatie "overschrijft" de gedelegeerde — dat wil zeggen, de methode die expliciet in de klasse is gedefinieerd, heeft voorrang:
class Service(logger: Logger): Logger by logger { override fun log(msg: String) = println("PREFIX: $msg") }
Kan één klasse meerdere interfaces aan verschillende objecten delegeren?
Ja, een klasse kan meerdere interfaces implementeren en deze aan verschillende objecten delegeren, maar elke interface wordt aan één object gedelegeerd:
class Service( logger: Logger, tracker: Tracker ): Logger by logger, Tracker by tracker
Wat is het verschil tussen interfacedelegatie en eigenschapdelegatie via by?
De klasse implementeert handmatig de interface, elk method aanroept het delegaat, en bij het toevoegen van nieuwe methoden vergeten ze de proxering bij te werken, wat tot fouten leidt.
Voordelen:
Nadelen:
Taaldelegatie wordt gebruikt, alleen niet-standaard methoden worden binnen de klasse geïmplementeerd, nieuwe functionaliteit wordt toegevoegd zonder grote wijzigingen.
Voordelen:
Nadelen: