What are the rules for supertypes in a Kotlin object expression, including supplying constructor arguments and combining multiple types?
answer
- One class + many interfaces after colon
- Superclass args after the type name
- Interfaces take no args
- Must override all abstract members
- super<Type>.member() disambiguates conflicts
basics
~10 sAfter the colon you can list one class plus any number of interfaces, separated by commas. If the class has a constructor, you pass its arguments right after the class name, like calling it.
solid answer
~40 sIn `object : Super1(args), Super2, Super3 { ... }`, you may extend at most one open/abstract class and implement any number of interfaces, all listed after the colon and comma-separated. If the superclass has a non-trivial constructor, you supply its arguments immediately after the type name — the same syntax as a class constructor call. Interfaces take no arguments. The anonymous object must satisfy all abstract members from every supertype, overriding them in the body with `override`. If two supertypes declare conflicting members, you must override explicitly and can disambiguate with `super<Type>.member()`. With no supertype at all, `object { }` is allowed and the implicit supertype is `Any`. This mirrors how a normal class declares its supertypes, just inlined at the use site.
code
kotlin · 9 linesinterface Closeable2 { fun close() }
open class Resource(val id: Int) { open fun open() = println("open $id") }
val r = object : Resource(7), Closeable2, Comparable<Int> {
override fun close() = println("close $id")
override fun compareTo(other: Int) = id - other
}
fun main() { r.open(); r.close(); println(r.compareTo(7)) }go deeper
Knows the body must override the interface methods it implements.
States the one-class-plus-many-interfaces rule, where constructor args go, and that all abstract members must be overridden.
Handles member conflicts with super<Type> and explains the parallel to normal class supertype declarations.
Judges when collapsing several roles into one anonymous object is clean vs when distinct named types are warranted for testability and clarity.
## Supertype list After the colon, an object expression lists its supertypes, comma-separated: ```kotlin interface A { fun a() } interface B { fun b() } open class Base(val name: String) { open fun describe() = name } val obj = object : Base("x"), A, B { override fun a() = println("a") override fun b() = println("b") override fun describe() = "obj:$name" } ``` ### Rules - **At most one class** (it must be `open` or `abstract`); **any number of interfaces**. - **Constructor arguments** for the superclass go right after the class name: `Base("x")`. Interfaces never take arguments. - All **abstract members** from every supertype must be implemented with `override`, or the code won't compile. - **No supertype** is allowed: `object { val x = 1 }` — implicit supertype is `Any`. ## Resolving conflicts If two supertypes provide a member with the same signature, you must **override it explicitly**. Use the qualified `super<Type>` form to call a specific parent implementation: ```kotlin interface Left { fun greet() = "left" } interface Right { fun greet() = "right" } val merged = object : Left, Right { override fun greet() = super<Left>.greet() + super<Right>.greet() } ``` ## Comparison to named classes The supertype rules are identical to a normal class declaration — single class + multiple interfaces, constructor delegation — only inlined. The difference is there is no class name and the instance is produced immediately. ## Gotchas - Trying to extend two classes is a compile error. - Forgetting constructor args for a superclass that needs them is an error. - An anonymous object can also add brand-new members beyond what the supertypes require.
- Can an object expression extend two classes?No. Like any Kotlin class it may extend at most one class but implement any number of interfaces.
- How do you call a specific parent's default method when two interfaces clash?Override the member and use the qualified super call `super<InterfaceName>.method()`.
saying these in an interview costs you the question
- Claiming you can extend multiple classes
- Putting constructor args on an interface
- Forgetting that all abstract members must be overridden
- Not knowing super<Type> disambiguation exists
- Saying a supertype is always required