Type inference of class type parameter in abstract method

Viewed 54
// Bars.kt
abstract class Bar
class BarToo(/* fields */) : Bar()

// Foos.kt
abstract class Foo<T : Bar> {
    abstract fun foo(bar: T)
}

class FooToo : Foo<BarToo>() {
    override fun foo(bar: BarToo) { /* */ }
}

// FoosBars.kt
private val foos = HashMap<String, Foo<out Bar>>()

fun <T : Foo<out Bar>> putFoo(name: String, foo: T) {
    foos.putIfAbsent(name, foo)
}

fun doFoo(name: String, bar: Bar) {
    val foo = foos[name] ?: return

    // Error: Type mismatch: inferred type is Bar but Nothing was expected
    // https://pl.kotl.in/TSp3eO_Tj
    foo.foo(bar)
}

If I manually specify the bounds of T at the method's declaration, the error in doFoo is resolved, e.g.:

abstract class Foo /* ... */ {
    abstract <T : Bar> fun foo(bar: T)
}

but obviously prevents the subclasses from using the type parameter from the class declaration.

Is this type of hierarchy possible in Kotlin, or should I better explain what I am trying to accomplish in order to avoid an XY problem?

Thanks!

1 Answers

You need to use in instead of out. This allows child classes to be used as follows:

foo.foo(bar)
foo.foo(BarToo()) // no compile error

Ref: this

Related