How can a class implement a generic interface, and what choices do you have for the interface's type parameter when you do?
answer
- Supply a type arg per interface parameter after the colon
- Fix it: class V : Comparable<V>
- Forward it: class Box<T> : Container<T>
- Partial fix: class IntMap<V> : Map<Int, V>
- override is mandatory; signature uses the substituted type
basics
~10 sWhen a class implements a generic interface, it either fixes the type argument to a concrete type (class IntBox : Container<Int>) or stays generic and forwards its own parameter (class Box<T> : Container<T>).
solid answer
~40 sA class implements a generic interface by supplying a **type argument** for each of the interface's type parameters in the supertype list. You have two choices. (1) **Fix** the argument to a concrete type: `class StringList : Comparable<StringList>` or `class Counter : Iterable<Int>` — the class is non-generic and the inherited members use the concrete type. (2) **Forward** the class's own parameter: `class Box<T> : Container<T>` — the class stays generic and passes its `T` straight through. You can also partially fix in multi-parameter interfaces: `class IntMap<V> : Map<Int, V>`. The overriding members must match the substituted signature exactly: implementing `Comparable<Foo>` means `override fun compareTo(other: Foo): Int`. The `override` keyword is mandatory in Kotlin.
code
kotlin · 16 linesinterface Container<T> { fun get(): T }
// forward the parameter
class Box<T>(private val v: T) : Container<T> {
override fun get(): T = v
}
// fix the parameter
class Version(val n: Int) : Comparable<Version> {
override fun compareTo(other: Version): Int = n.compareTo(other.n)
}
fun main() {
println(Box("hi").get())
println(Version(2).compareTo(Version(1)))
}go deeper
Can implement a generic interface by fixing the type argument to a concrete type with a correct override.
Knows both fixing and forwarding the class's own parameter, and that override signatures use the substituted type.
Handles partial fixing in multi-parameter interfaces and explains how interface variance carries to implementers.
Weighs whether to expose a concrete or still-generic implementation as the public type for API stability.
## Implementing a generic interface A generic interface declares one or more type parameters. When a class implements it, the class must **provide a type argument** for each parameter in the **supertype list** (after the colon). ## Option 1 — fix the type argument The implementing class is **not** generic; it nails the parameter to a concrete type: ```kotlin class Version(val n: Int) : Comparable<Version> { override fun compareTo(other: Version): Int = n.compareTo(other.n) } ``` Here `Comparable<in T>`'s `T` is fixed to `Version`, so `compareTo` takes a `Version`. The `override` keyword is **required**. ## Option 2 — forward the class's own parameter The implementing class **stays generic** and passes its own type parameter through: ```kotlin interface Container<T> { fun get(): T } class Box<T>(private val value: T) : Container<T> { override fun get(): T = value } ``` Now `Box<String>` is a `Container<String>`. The class's `T` and the interface's `T` are linked one-to-one. ## Option 3 — partial fixing (multi-parameter interfaces) With multiple parameters you can fix some and forward others: ```kotlin class IntKeyedMap<V> : Map<Int, V> { /* ... */ } ``` Here `K` is fixed to `Int`, `V` is forwarded. ## Signature matching Whatever you substitute, the **overriding member signatures must match the substituted interface signatures**. Implementing `Comparable<Version>` requires `override fun compareTo(other: Version): Int` — not `Any`, not `T`. Mismatches are compile errors. ## Variance carries over If the interface is declared `interface Source<out T>`, the relationship still holds for implementers: `Box<Cat> : Source<Cat>` is usable as `Source<Animal>`. You don't re-declare the variance on the implementing class; it comes from the interface. ## Extending generic classes The same rules apply to `open` generic classes via inheritance — `class StringBox : Box<String>()` fixes `T`, `class SubBox<T> : Box<T>()` forwards it. ## Summary - Provide a type argument per interface parameter in the supertype list. - Fix it (non-generic class), forward your own parameter, or fix some + forward others. - Override members with the substituted signature; `override` is mandatory.
- Can a class fix some type parameters and forward others when implementing a two-parameter interface?Yes. e.g. `class IntMap<V> : Map<Int, V>` fixes K to Int and forwards V as its own parameter.
- Does the overriding method use T or the substituted type in its signature?It must use the substituted type. Implementing Comparable<Version> requires `override fun compareTo(other: Version): Int`.
saying these in an interview costs you the question
- Forgetting the `override` keyword (mandatory in Kotlin)
- Writing the overriding method with `Any` or a raw type instead of the substituted type
- Thinking a class must always stay generic to implement a generic interface
- Re-declaring variance on the implementing class instead of inheriting it from the interface