Calling super

Extend, Do Not Replace

Inside an override, super.function() calls the parent version. Use it when the child should add behaviour instead of replacing it - exactly what Android does with super.onCreate().

Example

open class Logger {
    open fun log(msg: String) {
        println("LOG: $msg")
    }
}

class TimestampLogger : Logger() {
    override fun log(msg: String) {
        super.log("[10:30] $msg")
        println("   (saved to file)")
    }
}

fun main() {
    TimestampLogger().log("User logged in")
}

Output

LOG: [10:30] User logged in
   (saved to file)

Initialization Order

Example

The parent is fully initialised before the child's init runs.

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

class Derived(name: String, val level: Int) : Base(name.uppercase()) {
    init { println("2. Derived init, level $level") }
}

fun main() {
    Derived("android", 3)
}

Output

1. Base init for ANDROID
2. Derived init, level 3

Note: Never call an open function from a parent constructor or init: the child's properties are not yet initialised at that moment, so the override may see null or 0.

Secondary Constructors with super

When the child has no primary constructor, each secondary constructor calls super(...). This is common for Android custom views and exceptions.

class RoundedButton : AppCompatButton {
    constructor(context: Context) : super(context)
    constructor(context: Context, attrs: AttributeSet?) : super(context, attrs)
}

class ApiException : Exception {
    constructor(message: String) : super(message)
    constructor(message: String, cause: Throwable) : super(message, cause)
}