Delegacja interfejsu za pomocą operatora by pozwala klasie przekazywać wszystkie wywołania interfejsu do określonego obiektu-delegata. To zmniejsza duplikowanie kodu i realizuje wzorzec kompozycji (composition).
Przykład:
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
Różnice od delegacji właściwości:
val/var x by ...) dotyczy konkretnej właściwości i wymaga implementacji interfejsu delegata (na przykład ReadWriteProperty).Zalety:
Wady:
Czym delegacja interfejsu (
by) różni się od implementacji interfejsu z przekazaniem obiektu przez pole?
Odpowiedź:
Delegacja (przez by) automatycznie implementuje wszystkie metody interfejsu przez obiekt delegata. Jeśli natomiast po prostu przechowywać obiekt-delegata jako pole i wywoływać jego metody ręcznie, to należy ręcznie zdefiniować każdą metodę interfejsu — co prowadzi do duplikacji i błędów. Ponadto delegacja za pomocą by zwiększa czytelność i redukuje ilość kodu wzorcowego:
// Bez delegacji class Service2(private val logger: Logger): Logger { override fun log(message: String) = logger.log(message) }
Historia
W projekcie próbowano zaimplementować wzorzec dekoratora dla interfejsu Logger ręcznie, zapomniano zaimplementować dodatkową metodę interfejsu, która później została dodana do Logger. Projekt kompilował się, ale nowa funkcjonalność nie działała, ponieważ implementacja była "pustakiem". Delegacja interfejsu przez by pozwoliłaby uniknąć tego błędu: wszystkie nowe metody automatycznie byłyby zaimplementowane przez delegata.
Historia
Przy delegacji interfejsu przez by, programista nadpisał jedną z metod interfejsu, ale zapomniał, że pozostałe metody wciąż są przekazywane przez delegata. W rezultacie część funkcjonalności działała "nienormalnie" — błąd długo nie był wychwytywany w logice metod biznesowych.
Historia
Próbowano zaimplementować delegację kilku interfejsów z pokrywającymi się metodami przez by, pojawił się konflikt — kompilator zaczął zgłaszać błąd niejednoznaczności, konieczne było jawne nadpisanie dublujących się metod, w przeciwnym razie projekt nie kompilował się.