skip to content

Kotlin allows a class to implement multiple interfaces but extend only one class. How do interfaces act as multiple-supertype contracts, and what does the type see?

level: middleimportance: should knowfreq 50%

answer

  1. One class max, many interfaces, comma-separated
  2. Superclass gets `()`, interfaces are bare
  3. Object is a subtype of every listed supertype
  4. Mixin/capability composition, no shared state
  5. Same-signature defaults → diamond, must disambiguate

basics

~20 s

A class can list several interfaces after the colon, separated by commas, and must satisfy all of them. It then counts as each of those types, so it can be passed wherever any one of them is expected.

solid answer

~40 s

Kotlin supports single class inheritance but multiple interface implementation. You write `class C : A, B, C` listing one optional superclass plus any number of interfaces, comma-separated. The class must satisfy every abstract member of every interface; it inherits all their default methods/getters. The resulting type is a subtype of each supertype, so a `C` instance is usable anywhere an `A`, `B`, or `C` is required—this is how interfaces give you mixin-style composition without true multiple inheritance of state (interfaces carry no fields). Common patterns: `Comparable<T>` + `Closeable`, or composing fine-grained capability interfaces. When two implemented interfaces both provide the same default method, you hit a diamond and must override and disambiguate with `super<Interface>.method()`.

code

kotlin · 16 lines
kotlin
interface Drawable { fun draw() }
interface Clickable { fun click() = println("clicked") }

class Button : Drawable, Clickable {
    override fun draw() = println("drawing button")
    // click() inherited as default
}

fun render(d: Drawable) = d.draw()
fun handle(c: Clickable) = c.click()

fun main() {
    val b = Button()
    render(b)  // works: Button is Drawable
    handle(b)  // works: Button is Clickable
}

go deeper

for a junior

Knows a class can implement several interfaces by listing them comma-separated.

for a middle

Explains single-class/multi-interface rule, the () vs bare syntax, and that the object is a subtype of each supertype.

for a senior

Connects multiple interfaces to mixin composition, where-clause constraints, and why stateless interfaces avoid the state diamond.

for a principal

Designs capability-interface taxonomies and reasons about composition vs deep hierarchies for maintainable, polymorphic APIs.

## Single class, many interfaces Kotlin, like Java, has **single inheritance of classes** but **multiple implementation of interfaces**. The supertype list after `:` may contain at most one class and any number of interfaces: ```kotlin open class Entity interface Identifiable { val id: String } interface Auditable { val createdAt: Long; fun ageMillis(now: Long) = now - createdAt } class User( override val id: String, override val createdAt: Long, ) : Entity(), Identifiable, Auditable ``` Note the class is constructed with `Entity()` (parentheses = constructor call), while interfaces appear bare (`Identifiable`, `Auditable`) because they have no constructor. ## What 'multiple-supertype contract' means The class must **satisfy every contract**: implement all abstract members from all interfaces, and it inherits all their default members. The instance's type is a **subtype of each** listed supertype. So: ```kotlin val u: User = User("u1", 0) val a: Identifiable = u // OK — User is Identifiable val b: Auditable = u // OK — User is Auditable too ``` You can pass `u` to any function expecting `Identifiable` *or* `Auditable`. This is **mixin / capability composition**: small, focused interfaces combined to describe what a type can do. ## Why interfaces, not multiple class inheritance Interfaces carry **no state** (no backing fields, no constructor), so combining several causes no field-layout or initialization ambiguity. That is exactly why Kotlin allows unlimited interfaces but only one class — a class brings stored state and a constructor, and mixing several would create the classic state-diamond problem. ## Combining at the type level You can also require multiple supertypes in generics and `where` clauses: ```kotlin fun <T> persist(item: T) where T : Identifiable, T : Auditable { /* ... */ } ``` ## The diamond caveat If two implemented interfaces provide a default method with the **same signature**, the class inherits two competing bodies and won't compile until you override it and pick one with `super<TypeName>.member()`. (Full diamond resolution is its own topic; here just know multiple supertypes can collide on defaults.) ## Summary Multiple interfaces = multiple independent contracts a single object honors simultaneously, enabling composition and polymorphism across several axes without inheriting state.

  • Why must a superclass appear with parentheses but interfaces without?
    The parentheses invoke the superclass constructor (classes have constructors and state); interfaces have no constructor, so they are listed bare.
  • How do you require two interfaces on a generic type parameter?
    Use a `where` clause: `fun <T> f(t: T) where T : A, T : B`, which constrains `T` to be both `A` and `B`.

Interfaces are like job certifications: a person can hold many at once (driver, first-aider, lifeguard) and be hired for any role each one qualifies them for.

saying these in an interview costs you the question

  • Claiming Kotlin supports multiple class inheritance
  • Forgetting parentheses on the superclass in the supertype list
  • Thinking interfaces can share/inherit state across multiple supertypes
  • Not realizing same-signature defaults cause a compile error until disambiguated

context