Interfaces
Kotlin interfaces: methods + default impls, properties, multiple inheritance, and the patterns that keep API surfaces tidy.
Kotlin — interfaces
EXAMPLE
// ===== Basic =====
interface Greetable {
fun greet(): String
}
class User(val name: String) : Greetable {
override fun greet() = "Hi $name"
}
// ===== Default implementations =====
interface Greetable2 {
val name: String
fun greet() = "Hi $name" // default — implementers can override
}
class Bot(override val name: String) : Greetable2 // greet() inherited
// ===== Multiple inheritance + conflict resolution =====
interface A { fun act() = println("A") }
interface B { fun act() = println("B") }
class C : A, B {
override fun act() {
super<A>.act() // pick a specific parent's impl
super<B>.act()
}
}
// ===== Abstract properties =====
interface Repo<T> {
val name: String
fun find(id: Int): T?
}
class UserRepo : Repo<User> {
override val name = "users"
override fun find(id: Int): User? = null
}
// ===== Sealed interfaces (closed family) =====
sealed interface Result<out T> {
data class Ok<T>(val value: T) : Result<T>
data class Err(val msg: String) : Result<Nothing>
}
fun handle(r: Result<Int>) = when (r) {
is Result.Ok -> r.value
is Result.Err -> -1
}
// ===== Functional interface (SAM) =====
fun interface OnClick {
fun onClick(view: View)
}
// SAM conversion allows a lambda:
button.setListener { v -> println("clicked $v") }
// ===== Delegation (by) =====
class CachingRepo<T>(private val inner: Repo<T>) : Repo<T> by inner {
private val cache = mutableMapOf<Int, T>()
override fun find(id: Int): T? = cache.getOrPut(id) { inner.find(id) ?: return null }
override val name get() = "caching-${inner.name}"
}
// 'by inner' generates default delegating impls; override specific methods.
// ===== Companion + interface (static-like) =====
interface Factory<T> {
fun create(): T
}
class Order(val id: String) {
companion object : Factory<Order> {
override fun create() = Order(java.util.UUID.randomUUID().toString())
}
}
// Order.create() // uses companion implementing the interface
// ===== Patterns to internalise =====
// - Interfaces for behaviour contracts; abstract class for partial state
// - Default methods to evolve interfaces without breaking implementers
// - Sealed interfaces for exhaustive 'when' over closed hierarchies
// - 'by' delegation for decorator patterns
// ===== Pitfalls =====
// - Diamond inheritance without resolving super<X>
// - Default methods that depend on other unimplemented methods -> runtime gaps
// - Sealed interfaces across files in non-same module -> compile errors
// - Big 'God' interfaces -> split by responsibility (ISP)
Why it matters
Kotlin interfaces support default methods, properties, multiple inheritance with super
Tip: Tweak the snippet with Try it Yourself », then sit the quiz at the bottom of the page.
Example
Example
interface Greet {
fun hello(): String
fun wave() = "👋"
}
class User : Greet {
override fun hello() = "hi"
}
Try it Yourself »
Discussion
Loading…