Kotlin
Summary - Inheritance
Combine open, override and abstract to write a shape hierarchy.
Summary - Inheritance
In this group you learned inheritable classes with open, method redefinition with override, base behavior with super, contracts with abstract and interface implementation with interface.
Now you will combine them: an abstract base class, concrete subclasses inheriting it, and an implemented interface, forming a shape hierarchy. This structure is the backbone of Kotlin object-oriented programming. Later, sealed classes and generics will build on this foundation.
Exercise Combine the Shape hierarchy
Define an abstract class named Shape with a primary constructor taking val name: String. Add an abstract fun area(): Double method. Define a subclass named Square with a primary constructor taking name: String, val side: Double that inherits from Shape(name); its override fun area(): Double returns side * side. Define another subclass named Triangle with a primary constructor taking name: String, val base: Double, val height: Double that inherits from Shape(name); its override fun area(): Double returns 0.5 * base * height. In main create an instance of each subclass and print name and area.
Show example solution
abstract class Shape(val name: String) {
abstract fun area(): Double
}
class Square(name: String, val side: Double) : Shape(name) {
override fun area(): Double = side * side
}
class Triangle(name: String, val base: Double, val height: Double) : Shape(name) {
override fun area(): Double = 0.5 * base * height
}
fun main() {
val s = Square("Square", 4.0)
val t = Triangle("Triangle", 6.0, 3.0)
println("${s.name}: ${s.area()}")
println("${t.name}: ${t.area()}")
}
What comes next?
You learned inheritance and interfaces. In the next groups you will explore data classes, copying with copy and closed hierarchies with sealed classes.
This group combined open, override, super, abstract and interface. These are the foundations of Kotlin inheritance. Next you will see the methods that data classes generate automatically, such as equals, hashCode and toString.
Exercise The Paid interface and the Contractor class
Define an interface named Paid with a method fun pay(): Double. Define an open class named Employee with a primary constructor taking val name: String, val hourlyRate: Double and an open fun hours() = 40 method. Define a subclass named Contractor that inherits from Employee(name, hourlyRate), implements the Paid interface, and provides override fun hours() = 30 and override fun pay(): Double returning hourlyRate * hours(). In main create a Contractor instance and print name and pay.
Show example solution
interface Paid {
fun pay(): Double
}
open class Employee(val name: String, val hourlyRate: Double) {
open fun hours() = 40
}
class Contractor(name: String, hourlyRate: Double) : Employee(name, hourlyRate), Paid {
override fun hours() = 30
override fun pay(): Double {
return hourlyRate * hours()
}
}
fun main() {
val c = Contractor("Alex", 50.0)
println("${c.name} pay: ${c.pay()}")
}
Test yourself
-
Which modifier does a subclass use to redefine an open method of its base class?
- override
- open
- abstract
- final
Show answer
override — The override modifier marks a redefinition.
-
Complete the interface implementation
class Triangle : ____ {
override fun area() = 0.5 * base * height
}
Show answer
class Triangle : Shape {
override fun area() = 0.5 * base * height
}
Next lesson: data class