Clases abstractas y métodos abstractos en Kotlin

Clase 27 de 35Curso de Kotlin

Resumen

Las abstract classes y las interfaces son dos conceptos clave en la programación orientada a objetos que permiten estructurar código de manera eficiente. En este contenido profundizamos en entender qué son estas abstract classes, en qué se diferencian de las interfaces y en qué situaciones es recomendable utilizar cada una para lograr un código más limpio y escalable.

¿Qué es una abstract class y cómo funciona?

Una abstract class es una clase especial en programación que define métodos y variables para que otras clases, mediante la herencia, implementen sus funcionalidades. A diferencia de las clases comunes, estas no pueden instanciarse directamente, ya que contienen métodos abstractos y variables abstractas que deben ser obligatoriamente definidos por las subclases que heredan de ellas.

  • La declaración se realiza con la palabra reservada abstract.
  • Garantiza que cualquier clase que la extienda debe implementar sus métodos abstractos definidos en la clase base.

¿Cómo declarar una abstract class?

Para declarar una abstract class, sigue el modelo siguiente:

abstract class BaseEmailRepository {
    abstract fun save(email: String)
}

Cuando otra clase extiende esta clase abstracta, debe implementar el método.

¿En qué se diferencian abstract classes e interfaces?

La principal diferencia radica en cómo establecen relaciones entre las clases que las implementan:

  • Las abstract classes usan herencia, creando relaciones directas entre una clase padre y sus subclases. Esto implica una jerarquía y dependencia.
  • Las interfaces usan composición y no generan esta jerarquía. Permiten crear pequeñas funcionalidades encapsuladas y mantener clases más independientes.

Al decidir entre ellas, considera:

  • Usar abstract class si todas las variables o métodos se utilizarán frecuentemente en subclases.
  • Usar interfaces para pequeños contratos flexibles que no necesariamente requerirán todas sus variables o métodos en todas las implementaciones.

¿Qué implica el uso de herencia versus composición?

La herencia puede llevar a una acumulación de métodos y variables innecesarias en algunas clases hijas, mientras que la composición mediante interfaces permite un diseño modular y más liviano.

De este modo, interfaces ayudan a mantener un código ordenado y limpio, facilitando futuras modificaciones o ampliaciones.

Ejemplo práctico con abstract class

Aquí tienes un ejemplo práctico que ilustra cómo usar abstract class:

abstract class BaseEmailNotifier {
    abstract fun notify(email: String)
}

class ConsoleNotifier : BaseEmailNotifier() {
    override fun notify(email: String) {
        println("Email recibido: $email")
    }
}

fun main() {
    val notifier = ConsoleNotifier()
    notifier.notify("ejemplo@correo.com")
}

Recuerda, implementas la función notify obligatoriamente en la subclase cuando usas abstract class, algo similar a la implementación requerida por una interfaz, pero mediante herencia.

¿Cuándo elegir abstract class sobre interfaces?

Elige abstract class si: - Necesitas mantener y extender una lógica común de manera sencilla a través de múltiples implementaciones relacionadas por jerarquía.

Opta por interfaces cuando: - Prefieres flexibilidad y modularidad, evitando relaciones jerárquicas rígidas entre las clases que implementan funcionalidades similares.