Il delegare un'interfaccia usando l'operatore by consente a una classe di reindirizzare tutte le chiamate dell'interfaccia a un oggetto delegato specifico. Questo riduce la duplicazione del codice e implementa il pattern di composizione (composition).
Esempio:
interface Logger { fun log(message: String) } class ConsoleLogger: Logger { override fun log(message: String) = println("LOG: $message") } class Service(logger: Logger): Logger by logger { fun doWork() { log("Service is working") } } val service = Service(ConsoleLogger()) service.doWork() // LOG: Service is working
Differenze dal delegare proprietà:
val/var x by ...) si applica a una proprietà specifica e richiede l'implementazione dell'interfaccia del delegato (ad esempio, ReadWriteProperty).Pro:
Contro:
In cosa il delegare un'interfaccia (
by) è diverso dall'implementare un'interfaccia passando un oggetto tramite un campo?
Risposta:
Il delegato (tramite by) implementa automaticamente tutti i metodi dell'interfaccia attraverso l'oggetto delegato. Se si conserva semplicemente l'oggetto delegato come campo e si chiamano i suoi metodi manualmente, è necessario scrivere manualmente ogni metodo dell'interfaccia — il che porta a duplicazioni e errori. Inoltre, il delegato tramite by offre maggiore leggibilità e meno codice boilerplate:
// Senza delega class Service2(private val logger: Logger): Logger { override fun log(message: String) = logger.log(message) }
Storia
In un progetto hanno cercato di implementare il pattern decorator per l'interfaccia Logger a mano, dimenticando di implementare un metodo aggiuntivo dell'interfaccia, che è stato successivamente aggiunto a Logger. Il progetto si compilava, ma la nuova funzionalità non funzionava, poiché l'implementazione era "vuota". Il delegare un'interfaccia tramite by avrebbe evitato questo errore: tutti i nuovi metodi sono automaticamente implementati dal delegato.
Storia
Quando si delega un'interfaccia tramite by, lo sviluppatore ha ridefinito uno dei metodi dell'interfaccia, ma ha dimenticato che gli altri metodi vengono comunque passati attraverso il delegato. Di conseguenza, parte della funzionalità ha funzionato "in modo non standard" — l'errore non è stato rilevato a lungo nella logica dei metodi di business.
Storia
Hanno cercato di implementare il delegato di più interfacce con metodi sovrapposti tramite by, si è verificato un conflitto — il compilatore ha iniziato a restituire errori di ambiguità, è stato necessario sovrascrivere esplicitamente i metodi duplicati, altrimenti il progetto non si compilava.