Saltar a contenido

Concepto de Herencia

La herencia permite crear nuevas clases partiendo de una clase existente. Una subclase hereda automáticamente propiedades y métodos de su clase padre.

classDiagram
    Vehiculo <|-- Auto
    Vehiculo <|-- Moto
    Vehiculo <|-- Camion

    class Vehiculo{
      +marca: String
      +modelo: String
      +acelerar()
      +frenar()
    }

    class Auto{
      +numeroPuertas: Int
      +abrirMaletero()
    }

    class Moto{
      +tipoCasco: String
    }

    class Camion{
      +capacidadCarga: Double
      +descargar()
    }

Uso en Kotlin

open class Vehiculo(val marca: String, val modelo: String) {
    fun acelerar() = println("$marca $modelo acelerando...")
    fun frenar() = println("$marca $modelo frenando...")
}

class Auto(marca: String, modelo: String, val numeroPuertas: Int) 
    : Vehiculo(marca, modelo) {

    fun abrirMaletero() = println("Abriendo maletero…")
}

Herencia vs Colaboración

El primer tipo de relación que habíamos visto entre dos clases, es la de colaboración. Recordemos que es cuando una clase contiene un objeto de otra clase como atributo.

Cuando la relación entre dos clases es del tipo "...tiene un..." o "...es parte de...", no debemos implementar herencia. Estamos frente a una relación de colaboración de clases no de herencia.

Clases abstractas

En algunas situaciones tenemos métodos y propiedades comunes a un conjunto de clases, podemos agrupar dichos métodos y propiedades en una clase abstracta.

Hay una sintaxis especial en Kotlin para indicar que una clase es abstracta.

No se pueden definir objetos de una clase abstracta y seguramente será heredada por otras clases de las que si podremos definir objetos.

classDiagram
    FiguraGeometrica <|-- Circulo
    FiguraGeometrica <|-- Rectangulo

    class FiguraGeometrica{
      <<abstract>>
      +color: String
      +area()* Double
    }

    class Circulo{
      +radio: Double
      +area() Double
    }

    class Rectangulo{
      +base: Double
      +altura: Double
      +area() Double
    }
abstract class FiguraGeometrica(val color: String) {
    abstract fun area(): Double
}

class Circulo(color: String, val radio: Double) : FiguraGeometrica(color) {
    override fun area() = Math.PI * radio * radio
}

class Rectangulo(color: String, val base: Double, val altura: Double)
    : FiguraGeometrica(color) {
    override fun area() = base * altura
}

¿Qué hereda una subclase?

Hereda No hereda
Propiedades open Miembros private
Métodos open Constructores

Ejemplo

classDiagram
    Animal <|-- Perro
    Animal <|-- Gato

    class Animal{
    <<abstract>>
    +nombre: String
    +hablar()* String
    }

    class Perro{
    +hablar() String
    }

    class Gato{
    +hablar() String
    }
abstract class Animal(val nombre: String) {
    abstract fun hablar(): String
}

class Perro(nombre: String) : Animal(nombre) {
    override fun hablar() = "Guau guau"
}

class Gato(nombre: String) : Animal(nombre) {
    override fun hablar() = "Miau"
}
abstract class Animal(val nombre: String) {
    abstract fun hablar(): String
}

class Perro(nombre: String) : Animal(nombre) {
    override fun hablar() = "Guau guau"
}

class Gato(nombre: String) : Animal(nombre) {
    override fun hablar() = "Miau"
}
@Composable
fun FichaAnimal(animal: Animal) {
    Card(
        modifier = Modifier
            .fillMaxWidth()
            .padding(8.dp),
        elevation = CardDefaults.cardElevation()
    ) {
        Column(Modifier.padding(16.dp)) {
            Text("Animal: ${animal.nombre}")
            Text("Sonido: ${animal.hablar()}")
        }
    }
}
@Composable
fun ListaAnimales() {
    val animales: List<Animal> = listOf(
        Perro("Bobby"),
        Gato("Misu"),
        Perro("Toby")
    )

    LazyColumn {
        items(animales) { animal ->
            FichaAnimal(animal)
        }
    }
}

Actividad

  • PR 419 (RA2 / CE2a / IC2 / 5p). Crea un sistema orientado a objetos para gestionar animales de un centro veterinario. Representa el resultado mediante Jetpack Compose usando una lista dinámica con LazyColumn.

    1. Implementa una clase abstracta Animal, con:

      • nombre: String
      • edad: Int
      • genero: String
      • historial: HistorialClinico
      • Método abstracto fun sonido(): String
      • Método no abstracto fun descripcionBasica(): String
    2. Crea el data class HistorialClinico(vacunasAlDia: Boolean, observaciones: String).

    3. Implementa las subclases:

      • Perro → propiedad raza: String, método necesitaPaseo()
      • Gato → propiedad color: String, método esPeligroso()
      • Conejo → propiedad peso: Double, método dieta()
    4. Construye una lista polimórfica de varios animales.

    5. Implementa un composable FichaAnimal(animal: Animal) que muestre:

      • Nombre
      • Edad
      • Género
      • Sonido polimórfico
      • Historial clínico
    6. Crea un composable DetalleEspecifico(animal) que, usando when (animal), muestre datos específicos:

      • Perro → raza, necesitaPaseo()
      • Gato → color, esPeligroso()
      • Conejo → peso, dieta()
    7. Muestra los animales en una LazyColumn, cada uno dentro de una Card.