La delegación de una interfaz mediante el operador by permite que una clase dirija todas las llamadas a la interfaz a un objeto delegado específico. Esto reduce la duplicación de código y implementa el patrón de composición.
Ejemplo:
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
Diferencias con la delegación de propiedades:
val/var x by ...) se aplica a una propiedad específica y requiere la implementación de la interfaz del delegado (por ejemplo, ReadWriteProperty).Ventajas:
Desventajas:
¿En qué se diferencia la delegación de una interfaz (
by) de la implementación de la interfaz pasando el objeto a través de un campo?
Respuesta:
La delegación (a través de by) implementa automáticamente todos los métodos de la interfaz a través del objeto delegado. Si simplemente almacenas el objeto delegado como un campo y llamas a sus métodos manualmente, debes escribir manualmente cada método de la interfaz, lo que lleva a duplicaciones y errores. Además, la delegación a través de by ofrece mayor legibilidad y menos código boilerplate:
// Sin delegación class Service2(private val logger: Logger): Logger { override fun log(message: String) = logger.log(message) }
Historia
En un proyecto intentaron implementar el patrón decorador para la interfaz Logger manualmente, olvidaron implementar un método adicional de la interfaz que luego fue añadido a Logger. El proyecto se compilaba, pero la nueva funcionalidad no funcionaba, ya que la implementación era "vacía". La delegación de la interfaz a través de by habría evitado este error: todos los nuevos métodos serían implementados automáticamente por el delegado.
Historia
Al delegar una interfaz a través de by, el desarrollador sobrescribió uno de los métodos de la interfaz, pero olvidó que los otros métodos aún pasaban por el delegado. Como resultado, parte de la funcionalidad funcionaba de manera "no estándar" — el error no fue detectado durante mucho tiempo en la lógica de los métodos de negocio.
Historia
Intentaron implementar la delegación de múltiples interfaces con métodos superpuestos a través de by, surgió un conflicto — el compilador comenzó a mostrar un error de ambigüedad, tuvieron que sobrescribir explícitamente los métodos duplicados, de lo contrario, el proyecto no se compilaba.