If I have a class like the following:
class SimpleClass {
var test: Int = 1
}
I can do something like this:
inline fun <reified T : SimpleClass> myFunction1(): T {
//Do something with T
}
But if I have a class with generics:
class ComplexClass<T> {
var test: T? = null
}
How can I do the same?
The following doesn't work:
inline fun <reified T : ComplexClass<C>> myFunction2(): T {
//Do something with T
//Do something with C
}
How can I do it?
Here is a more complex example, if needed.
CodePudding user response:
Let's take a look at your example
class Mediator {
//It does't work! My question is about this function.
inline fun <reified T : Container<C>> mediate(string: String): T {
if (C::class == Child1::class)
//Do something
if (C::class == Child2::class)
//Do something else
}
}
class UseExample : Mediator() {
fun example1(): Container<Child1> {
return mediate("test1") // your mediate function does not take
// any parameters to determine the generic type
}
fun example2(): Container<Child2> {
return mediate("test2")
}
}
To perform something with the type C
which is used to create Container<C>
and perform something with the result type which you represent as T : Container<C>
you only need to know the C
. Since reified
can only be used to keep the type if it is known during the compile time at the call site, rewrite your function signature like this.
inline fun <reified C> mediate(string: String): Container<C> {
// now you know the C and you know the T which is Container<C>
if (C::class == Child1::class) ...
// Since T depends on C, you can only check the C type to perform logic
}
Use it like following
fun example1(): Container<Child1> {
return mediate<Child1>("test") // Note that know your C
// type is known at the function call therefore compiler
// can substitute it with exact type
}
Here is my minimal example from Kotlin Playground
class Container<T>(t: T) {
val smth : T = t
}
class Mediator {
inline fun <reified C> mediate(string: String): Container<C> {
if (C::class == Int::class) {
println("Int")
return Container<Int>(1) as Container<C>
}
throw IllegalStateException("Yopta")
}
}
fun main() {
val m = Mediator()
m.mediate<Int>("ABC") // Output is "Int"
}