sábado, 13 de agosto de 2022

Interfaces en Kotlin


Las interfaces de Kotlin son similares a las de Java 8: pueden contener definiciones de métodos abstractos, así como implementaciones de métodos no abstractos (similares a los métodos predeterminados de Java 8), pero no pueden contener ningún estado. Para declarar una interfaz en Kotlin, se usa la palabra clave de interface en lugar de class.


interface Clickable {

    fun click()

}


Esto declara una interfaz con un solo método abstracto llamado clic. Todas las clases no abstractas que implementan la interfaz deben proporcionar una implementación de este método. 

class Button : Clickable { override fun click() = println("I was clicked") } 

>>> Button().click() 

I was clicked


Kotlin usa los dos puntos después del nombre de la clase para reemplazar las palabras clave extends e implements que se usan en Java. Como en Java, una clase puede implementar tantas interfaces como quiera, pero solo puede extender una clase.

El modificador override, similar a la anotación @Override en Java, se utiliza para marcar métodos y propiedades que anulan los de la superclase o la interfaz. A diferencia de Java, el uso del modificador de anulación es obligatorio en Kotlin. Esto le evita anular accidentalmente un método si se agrega después de escribir su implementación; su código no se compilará a menos que marque explícitamente el método como anulado o le cambie el nombre.

Un método de interfaz puede tener una implementación predeterminada. A diferencia de Java 8, que requiere que marques tales implementaciones con la palabra clave predeterminada, Kotlin no tiene una anotación especial para tales métodos: solo proporcionas un cuerpo de método. Cambiemos la interfaz Clickable agregando un método con una implementación predeterminada


interface Clickable { 

  fun click() 

  fun showOff() = println("I'm clickable!") 

}


Si implementa esta interfaz, debe proporcionar una implementación para hacer clic. Puede redefinir el comportamiento del método showOff o puede omitirlo si está de acuerdo con el comportamiento predeterminado. Supongamos ahora que otra interfaz también define un método showOff y tiene la siguiente implementación para él.


interface Focusable {

    fun setFocus(b: Boolean) = println("I ${if (b) "got" else "lost"} focus.")

    fun showOff() = println("I'm focusable!")

}


¿Qué sucede si necesita implementar ambas interfaces en su clase? Cada uno de ellos contiene un método showOff con una implementación predeterminada; ¿Qué implementación gana? Ninguno de los dos gana. En su lugar, obtiene el siguiente error del compilador si no implementa showOff explícitamente


The class 'Button' must override public open fun showOff() because it inherits many implementations of it


El compilador de Kotlin te obliga a proporcionar tu propia implementación.


class Button : Clickable, Focusable { 

    override fun click() = println("I was clicked")

    override fun showOff() { 

        super<Clickable>.showOff()

        super<Focusable>.showOff() } 

}


La clase Button ahora implementa dos interfaces. Implementa showOff() llamando a ambas implementaciones que heredó de los supertipos. Para invocar una implementación heredada, usa la misma palabra clave que en Java: super. Pero la sintaxis para seleccionar una implementación específica es diferente. Mientras que en Java puede colocar el nombre del tipo base antes de la palabra clave super, como en Clickable.super.showOff(), en Kotlin coloca el nombre del tipo base entre paréntesis angulares: super<Clickable>.showOff().

Si solo necesita invocar una implementación heredada, puede escribir esto:


override fun showOff() = super.showOff()


Puede crear una instancia de esta clase y verificar que se pueden llamar todos los métodos heredados


fun main(args: Array) { 

    val button = Button() 

    button.showOff() 

    button.setFocus(true) 

    button.click() 

}


La implementación de setFocus se declara en la interfaz Focusable y se hereda automáticamente en la clase Button.   

No hay comentarios.:

Publicar un comentario