Inheritance, overrides and safe casts
Inheritance, overrides and safe casts
A school has a general person description and a specialized teacher description. Class inheritance can express a specialization, and an override replaces an inherited implementation. It should model a genuine substitutable relationship rather than merely avoid copying a few lines.
What you’ll learn
- Trace an override through a base reference.
- Handle a mismatched safe cast.
Inheritance, overrides and safe casts in the example
Superclass reference
A school has a general person description and a specialized teacher description.
Superclass referenceSubclass instance
Kotlin classes and members are final by default.
Subclass instanceOverridden behaviour
The reference’s declared type is Person, but its instance is Teacher.
Overridden behaviour
Understand inheritance, overrides and safe casts
Kotlin classes and members are final by default. Mark a class and overridable member open when specialization is intended, and use override in the subclass. A safe cast with as? returns null on a mismatch, while an unchecked as can fail. Is checks type membership and can enable a smart cast.
Follow inheritance, overrides and safe casts
Save the complete source as Main.kt and use the Kotlin/JVM environment. No separate input file is needed.
Kotlin/JVM · complete program
open class Person {
open fun role(): String = "Person"
}
class Teacher : Person() {
override fun role(): String = "Teacher"
}
fun main() {
val person: Person = Teacher()
println(person.role())
println(person is Teacher)
println((person as? Teacher)?.role() ?: "Other")
}Expected output
Teacher
true
TeacherFollow the execution
The reference’s declared type is Person, but its instance is Teacher. The override supplies Teacher at runtime, the is check succeeds and the safe cast allows the same role call.
Try this in the Kotlin compiler by pasting the complete program.
Practice: Inheritance, overrides and safe casts
Your task: What does as? Teacher produce for an ordinary Person instance?
Kotlin/JVM · complete program
open class Person {
open fun role(): String = "Person"
}
class Teacher : Person() {
override fun role(): String = "Teacher"
}
fun main() {
val person: Person = Teacher()
println(person.role())
println(person is Teacher)
println((person as? Teacher)?.role() ?: "Other")
}Worked answer
It returns null. A safe cast checks the existing instance rather than creating a teacher.
Inheritance, overrides and safe casts: the important boundary
Inheritance should express a substitutable relationship, not merely reuse a few lines. Prefer an interface or composition for unrelated capabilities. Do not assume Java’s or Swift’s default overridability rules apply.
Check your understanding
Inheritance, overrides and safe casts: what to keep in mind
It returns null. A safe cast checks the existing instance rather than creating a teacher. Inheritance should express a substitutable relationship, not merely reuse a few lines.
Further reading: official Kotlin documentation for this topic.
Reaching the recap and completing the quizzes are separate milestones.