Menu
Coddy logo textTech

super e Construtores

Parte da seção Programação Orientada a Objetos do Journey de Kotlin da Coddy. Lição 19 de 57.

super.method() chama a versão da superclasse de um método de dentro de uma sobrescrita. Uma subclasse pode estender o comportamento herdado em vez de substituí-lo:

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())

Saída:

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

Toda subclasse deve chamar um construtor da superclasse. Com um construtor primário, a chamada faz parte do cabeçalho, : Base(arguments), e os argumentos podem ser calculados a partir dos parâmetros da subclasse:

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)")

Saída:

tea 450 (10% off)

A criação ocorre do topo da hierarquia para baixo: os inicializadores de propriedades e os blocos init da superclasse são executados primeiro, depois os da subclasse:

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")

Saída:

Base init for KIT
Child init for kit

Uma classe sem um construtor primário chama a superclasse a partir de cada construtor secundário com super(...) ou delega para outro de seus próprios construtores com 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}")

Saída:

rect 3x3

Como a superclasse é configurada primeiro, ela não deve chamar membros open em seu construtor ou init. A sobrescrita é executada antes que as próprias propriedades da subclasse tenham seus 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()

Saída:

Base sees: label is null
challenge icon

Desafio

Fácil

Notification(text) tem um método aberto render() que retorna [info] text. Complete as subclasses: o render() de Warning retorna [warn] TEXT com o texto em letras maiúsculas, e Reminder, que também armazena minutes, retorna o resultado da superclasse seguido de (in 10 min), usando super.

O código fornecido lê linhas info,text, warn,text ou remind,text,10, cria o objeto correspondente em uma única List<Notification> e imprime render() para cada um.

Seu código deve ficar em Notification.kt, Warning.kt e Reminder.kt. Main.kt contém o código fornecido de entrada/saída e não pode ser editado.

Experimente você mesmo

fun main() {
    // Código de entrada/saída fornecido: mantenha-o 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 iconTeste seus conhecimentos

Esta lição inclui um quiz rápido. Comece a lição para respondê-lo e acompanhar seu progresso.

Todas as lições de Programação Orientada a Objetos

Pratique por conta própria: Playground de Kotlin