Menu
Coddy logo textTech

super y constructores

Parte de la sección Programación orientada a objetos del Journey de Kotlin de Coddy. Lección 19 de 57.

super.method() llama a la versión de la superclase de un método desde dentro de una sobrescritura. Una subclase puede ampliar el comportamiento heredado en lugar de reemplazarlo:

open class Notification(val text: String) {
    open fun render() = "[info] $text"
}
class Reminder(text: String, val minutes: Int) : Notification(text) {
    override fun render() = super.render() + " (in $minutes min)"
}

Dentro de main:

println(Notification("backup done").render())
println(Reminder("meeting", 10).render())

Salida:

[info] backup done
[info] meeting (in 10 min)

Cada subclase debe llamar a un constructor de la superclase. Con un constructor principal, la llamada forma parte de la cabecera, : Base(arguments), y los argumentos se pueden calcular a partir de los parámetros de la subclase:

open class Product(val name: String, val price: Int)

class Discounted(name: String, price: Int, val percent: Int) :
    Product(name, price * (100 - percent) / 100)

Dentro de main:

val tea = Discounted("tea", 500, 10)
println("${tea.name} ${tea.price} (${tea.percent}% off)")

Salida:

tea 450 (10% off)

La creación se ejecuta desde la parte superior de la jerarquía hacia abajo: los inicializadores de propiedades y los bloques init de la superclase se ejecutan primero, después los de la subclase:

open class Base(name: String) {
    init { println("Base init for $name") }
}
class Child(name: String) : Base(name.uppercase()) {
    init { println("Child init for $name") }
}

Dentro de main:

Child("kit")

Salida:

Base init for KIT
Child init for kit

Una clase sin un constructor primario llama a la superclase desde cada constructor secundario con super(...), o delega en otro de sus propios constructores con this(...):

open class Shape(val name: String)

class Rect : Shape {
    val w: Int
    val h: Int

    constructor(w: Int, h: Int) : super("rect") {
        this.w = w
        this.h = h
    }

    constructor(side: Int) : this(side, side)
}

Dentro de main:

val r = Rect(3)
println("${r.name} ${r.w}x${r.h}")

Salida:

rect 3x3

Como la superclase se configura primero, no debería llamar a miembros open desde su constructor o init. La sobrescritura se ejecuta antes de que las propias propiedades de la subclase tengan sus valores:

open class Base {
    init { println("Base sees: ${describe()}") }
    open fun describe() = "base"
}
class Child : Base() {
    val label = "child"
    override fun describe() = "label is $label"
}

Dentro de main:

Child()

Salida:

Base sees: label is null
challenge icon

Desafío

Fácil

Notification(text) tiene un método abierto render() que devuelve [info] text. Completa las subclases: el render() de Warning devuelve [warn] TEXT con el texto en letras mayúsculas, y Reminder, que también almacena minutes, devuelve el resultado de la superclase seguido de (in 10 min), usando super.

El código proporcionado lee líneas info,text, warn,text o remind,text,10, construye el objeto correspondiente en una sola List<Notification> e imprime render() para cada uno.

Tu código va en Notification.kt, Warning.kt y Reminder.kt. Main.kt contiene el código proporcionado de entrada/salida y no se puede editar.

Pruébalo tú mismo

fun main() {
    // Código de entrada/salida suministrado: mantenlo como está
    val input = generateSequence(::readLine).toList()
    val notes = mutableListOf<Notification>()
    for (line in input) {
        val p = line.split(",")
        notes.add(when (p[0]) {
            "warn" -> Warning(p[1])
            "remind" -> Reminder(p[1], p[2].toInt())
            else -> Notification(p[1])
        })
    }
    for (n in notes) println(n.render())
}
quiz iconPonte a prueba

Esta lección incluye un breve cuestionario. Empieza la lección para responderlo y registrar tu progreso.

Todas las lecciones de Programación orientada a objetos

Practica por tu cuenta: Playground de Kotlin