Is it somehow possible to have smart casts with ty...
# announcements
d
Is it somehow possible to have smart casts with type parameters? I have a situation where I have
interface Base<T>
and
Concrete<T : Any> : Base<T>
. In a method which accepts
Base<T>
I now need to check
is Concrete<T>
, but that's impossible because in the method
T
is not constrained to
Any
(but it has to be, if I have a
Concrete<T>
... See thread for more code.
Copy code
interface Base<T> {
    fun foo(): T = TODO()
}
class Concrete<T : Any> : Base<T> {
    fun otherFoo(): T = TODO()
}

fun <T> acceptBase(base: Base<T>): T = when (base) {
    is Concrete<*> -> acceptConcrete(base) // <- this does not compile
    else -> base.foo()
}

fun <T : Any> acceptConcrete(c: Concrete<T>) = c.otherFoo()
c
try this:
Copy code
fun <T: Any> acceptBase(base: Base<T>): T = when (base) {
        is Concrete -> acceptConcrete(base)
        else -> base.foo()
    }
d
Yes, but I can't call this with a
Base<Foo?>
c
If you need it to be optional, try this:
Copy code
interface Base<T> {
        fun foo(): T = TODO()
    }
    class Concrete<T : Any?> : Base<T> {
        fun otherFoo(): T = TODO()
    }
    fun <T: Any?> acceptBase(base: Base<T>): T = when (base) {
        is Concrete -> acceptConcrete(base) // <- this does not compile
        else -> base.foo()
    }
    fun <T : Any?> acceptConcrete(c: Concrete<T>) = c.otherFoo()

    class Foo {

    }

    fun test() {
        val base = acceptBase(Concrete<Foo?>())
    }
d
This allows me to make a
Concrete<Foo?>
, which must be forbidden.
Concrete
refines the constraints on
Base
.
Base
allows nulls,
Concrete
does not.
s
does inline / reified work?
Copy code
interface Base<T: Any> {
    fun foo(): T = TODO()
}
class Concrete<T : Any> : Base<T> {
    fun otherFoo(): T = TODO()
}
inline fun <reified T: Any> acceptBase(base: Base<T>): T = when (base) {
    is Concrete -> acceptConcrete(base) // <- this does not compile
    else -> base.foo()
}
fun <T : Any> acceptConcrete(c: Concrete<T>): T = c.otherFoo()
d
I cannot call
acceptBase
with a
Base<Foo?>
there.
And you have also changed
Base
to no longer accept nulls.