Abstract Classes
Abstract classes in Kotlin are similar to abstract classes in Java and Scala, but Kotlin makes a clear distinction about which methods are considered “open” to be overridden.
Key points
- Abstract classes are similar to Java’s abstract classes
- If you declare a class
abstract
it can’t be instantiated - Abstract classes can have:
- Abstract and concrete methods
- Abstract and concrete properties (fields)
- Abstract classes and abstract members don’t have to be annotated with
open
; the fact that they are abstract implies that they are intended to be overridden - Abstract classes can have private and protected members
Functions in abstract classes
Functions can be:
- Abstract: function signature only, no body
- Concrete, but closed (i.e., final)
- Concrete, and open to modification
Example:
abstract class Pet (name: String) {
abstract fun comeToMaster(): Unit //abstract, open by default
fun walk(): Unit = println("I’m walking") //concrete, closed (final)
open fun speak(): Unit = println("Yo") //concrete, open
}
Working code
Here’s a small, complete example that shows how abstract classes and functions work with inheritance:
abstract class Pet (name: String) {
abstract fun comeToMaster(): Unit //abstract, open by default
fun walk(): Unit = println("I’m walking") //concrete, closed (final)
open fun speak(): Unit = println("Yo") //concrete, open
}
class Dog(name: String) : Pet(name) {
override fun speak() = println("Woof")
override fun comeToMaster() = println("Here I come!")
}
class Cat(name: String) : Pet(name) {
override fun speak() = println("Meow")
override fun comeToMaster() = println("That’s not gonna happen")
}
fun main(args: Array<String>) {
val d = Dog("Zeus")
d.walk()
d.speak()
d.comeToMaster()
val c = Cat("Rusty")
c.walk()
c.speak()
c.comeToMaster()
}
Other abstract class features
Abstract classes can also have private properties, abstract properties, and concrete properties, as shown in the last three lines of this example:
abstract class Pet (name: String) {
abstract fun comeToMaster(): Unit //abstract method
fun walk(): Unit = println("I’m walking") //concrete, closed (final)
open fun speak(): Unit = println("Yo") //concrete, open
private var numberOfLegs = 4 //private
abstract var furColor: String //abstract (no initial value)
var actuallyLikesPeople = false //concrete, must have a value
}
Why use abstract classes (instead of interfaces)?
Interfaces can’t have constructor parameters, initialized properties, or private properties.
You can kind of simulate properties with default values, but interface properties can’t have backing fields:
interface Cat {
private var numLegs: Int
get() = 4
set(value) = TODO() //can’t use `field`
}
A note about designing base classes
This Reddit post has an interesting discussion about designing base classes. One interesting quote:
"Designing a base class, you should therefore avoid using open members in the constructors, property initializers, and init blocks."
See that Reddit link and this Kotlin link for more details.