33 - POO - 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.

Problema 1:

Declarar una clase abstracta que represente una Operación. Definir en la misma tres propiedades valor1, valor2 y resultado, y dos métodos: calcular e imprimir.
Plantear dos clases llamadas Suma y Resta que hereden de la clase Operación.

Proyecto140 - Principal.kt

abstract class Operacion(val valor1: Int, val valor2: Int) {
    protected var resultado: Int = 0

    abstract fun operar()

    fun imprimir() {
        println("Resultado: $resultado")
    }
}

class Suma(valor1: Int, valor2: Int): Operacion(valor1, valor2) {
    override fun operar() {
        resultado = valor1 + valor2
    }
}

class Resta(valor1: Int, valor2: Int): Operacion(valor1, valor2) {
    override fun operar() {
        resultado = valor1 - valor2
    }
}

fun main(parametro: Array<String>) {
    val suma1 = Suma(10, 4)
    suma1.operar()
    suma1.imprimir()
    val resta1 = Resta(20, 5)
    resta1.operar()
    resta1.imprimir()
}

Una clase abstracta se la declara antecediendo la palabra clave abstract a la palabra clave class:

abstract class Operacion(val valor1: Int, val valor2: Int) {

Podemos definir propiedades que serán heredables:

    protected var resultado: Int = 0

Podemos declarar métodos abstractos que obligan a las clases que heredan de esta a su implementación (esto ayuda a unificar las funcionalidades de todas sus subclases, tiene sentido que toda clase que herede de la clase Operación implemente un método operar):

    abstract fun operar()

Una clase abstracta puede tener también métodos concretos, es decir implementados:

    fun imprimir() {
        println("Resultado: $resultado")
    }

La sintaxis para declarar que una clase hereda de una clase abstracta es lo mismo que vimos en el concepto anterior:

class Suma(valor1: Int, valor2: Int): Operacion(valor1, valor2) {

Lo que si es obligatorio implementar el método abstracto operar, en caso que no se lo haga aparece un error sintáctico:

    override fun operar() {
        resultado = valor1 + valor2
    }

En la función main podemos definir objetos de la clave Suma y Resta, pero no podemos definir objetos de la clase Operacion ya que la misma es abstracta:

fun main(parametro: Array<String>) {
    val suma1 = Suma(10, 4)
    suma1.operar()
    suma1.imprimir()
    val resta1 = Resta(20, 5)
    resta1.operar()
    resta1.imprimir()
}

Problema propuesto

  • Declarar una clase abstracta Cuenta y dos subclases CajaAhorra y PlazoFijo. Definir las propiedades y métodos comunes entre una caja de ahorro y un plazo fijo y agruparlos en la clase Cuenta.
    Una caja de ahorro y un plazo fijo tienen un nombre de titular y un monto. Un plazo fijo añade un plazo de imposición en días y una tasa de interés. Hacer que la caja de ahorro no genera intereses.
    En la función main del programa definir un objeto de la clase CajaAhorro y otro de la clase PlazoFijo.
Solución
Proyecto141

abstract class Cuenta(val titular: String, val monto: Double) {
    open fun imprimir() {
        println("Titular: $titular")
        println("Monto: $monto")
    }
}

class CajaAhorro(titular: String, monto: Double): Cuenta(titular, monto) {
    override fun imprimir() {
        println("Cuenta de caja de ahorro")
        super.imprimir()
    }
}

class PlazoFijo(titular: String, monto: Double, val plazo: Int, val interes: Double): Cuenta(titular, monto) {
    override fun imprimir() {
        println("Cuenta de plazo fijo")
        println("Plazo en dias: $plazo")
        println("Intereses: $interes")
        val ganancia =  monto * interes / 100
        println("Importe del interes: $ganancia")
        super.imprimir()
    }
}

fun main(parametro: Array<String>) {
    val cajaAhorro1 = CajaAhorro("juan", 10000.0)
    cajaAhorro1.imprimir()
    val plazoFijo1 = PlazoFijo("Ana", 5000.0, 30, 1.23)
    plazoFijo1.imprimir()
}