Josh
Josh

Reputation: 1718

Kotlin Generic Reflection Subclass

I have a function that takes a Class<GenericType<Constraint>>. When I pass a subclass of that GenericType<Constraint> the compiler errors with the message: Type Inference Failed. Expected Type Mismatch

However, if I cast the type to it's supertype, it runs fine (with a warning). How to do this without casting?

open class Bag<T>

class IntBag: Bag<Int>()

fun testStuff(type: Class<Bag<Int>>) {
    // Do stuff
}

testStuff(IntBag::class.java) // This won't compile
testStuff(IntBag::class.java as Class<Bag<Int>>) // This compiles with a warning, but runs fine

Upvotes: 1

Views: 383

Answers (3)

Alexey Romanov
Alexey Romanov

Reputation: 170745

BUT if I cast the type to it's supertype, it runs fine (with a warning).

Well, it'll also "run fine" (depending on the internals of testStuff) if you do

testStuff(String::class.java as Class<Bag<Int>>)

Due to type erasure a Class<String> can be cast to Class<Anything> and this applies to other generic types too. But really, IntBag::class.java is a Class<IntBag> and not a Class<Bag<Int>>.

In fact, there are no values of type Class<Bag<Int>>; if you want Class<any subtype of Bag<Int>>, then Pamela Hill's answer gives the syntax.

Upvotes: 0

Seaskyways
Seaskyways

Reputation: 3795

Bag<Int> is effectively different than IntBag since they're different classes.

You could utilize a typealias for IntBag like so:

typealias IntBag = Bag<Int>

Upvotes: 0

Pamela Hill
Pamela Hill

Reputation: 99

You'll have to use out variance: fun testStuff(type: Class<out Bag<Int>>)

https://kotlinlang.org/docs/reference/generics.html

Upvotes: 2

Related Questions