Menu
Coddy logo textTech

super and Constructors

Part of the Object Oriented Programming section of Coddy's Kotlin journey. Lesson 19 of 57.

super.method() calls the superclass's version of a method from inside an override. A subclass can extend the inherited behaviour instead of replacing it:

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

Inside main:

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

Output:

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

Every subclass must call a superclass constructor. With a primary constructor, the call is part of the header, : Base(arguments), and the arguments can be computed from the subclass's parameters:

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

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

Inside main:

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

Output:

tea 450 (10% off)

Creation runs from the top of the hierarchy down: the superclass's property initializers and init blocks run first, then the subclass's:

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

Inside main:

Child("kit")

Output:

Base init for KIT
Child init for kit

A class without a primary constructor calls the superclass from each secondary constructor with super(...), or delegates to another of its own constructors with 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)
}

Inside main:

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

Output:

rect 3x3

Because the superclass is set up first, it should not call open members from its constructor or init. The override runs before the subclass's own properties have their values:

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

Inside main:

Child()

Output:

Base sees: label is null
challenge icon

Challenge

Easy

Notification(text) has an open method render() that returns [info] text. Complete the subclasses: Warning's render() returns [warn] TEXT with the text in capital letters, and Reminder, which also stores minutes, returns the superclass result followed by (in 10 min), using super.

The supplied code reads lines info,text, warn,text or remind,text,10, builds the matching object in one List<Notification> and prints render() for each.

Your code goes in Notification.kt, Warning.kt and Reminder.kt. Main.kt holds the supplied input/output code and cannot be edited.

Try it yourself

fun main() {
    // Supplied input/output code: keep it as it is
    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 iconTest yourself

This lesson includes a short quiz. Start the lesson to answer it and track your progress.

All lessons in Object Oriented Programming

Practice on your own: Kotlin playground