Francesc
08/23/2023, 4:40 PMreified
so that I get the type of the parent instead of a generic type, but I get an error that reads
Cannot use "CapturedType(out Root)" as reified type parameter
I have the sample code in the thread. Any suggestions how to go about this?Francesc
08/23/2023, 4:41 PMobject Bindings {
val map = mutableMapOf<KClass<out Scope>, Scope>()
inline fun <reified T : Scope> register(value: T) {
map[T::class] = value
}
inline fun <reified T : Scope> get(key: KClass<T>): T {
return map[key] as T
}
}
interface Scope {
val parent: Scope?
}
object Root : Scope {
override val parent: Scope? = null
fun something() {
println("Something called")
}
}
object Child : Scope {
override val parent: Root = Root
}
fun main() {
Bindings.register(Root)
Bindings.register(Child)
val parent = Bindings.get(key = Child.parent::class) <-- error here
parent.something()
}
Youssef Shoaib [MOD]
08/23/2023, 6:42 PMget
function doesn't need to be reified. I believe you can just remove the reified there and the code should compileYoussef Shoaib [MOD]
08/23/2023, 6:47 PMChild.parent
and Bindings.get(Child.parent::class)
will have the same value and the same type in the type systemFrancesc
08/23/2023, 7:18 PMreified
you can't cast to T and you get a generic scope. This is a contrived example, but I would like to understand how to get it to workYoussef Shoaib [MOD]
08/23/2023, 7:20 PMget
needs no knowledge of the reified type of T, only of its class. The caller to get
, when they use some reified type parameter T, will then cause the return value to be casted to T, thus the compiler will add a check in the bytecode to ensure that the type of the value is correctFrancesc
08/23/2023, 7:33 PMYoussef Shoaib [MOD]
08/23/2023, 7:38 PMget
be reified makes is that, at runtime, it does a check on the value that was gotten from the Map. That check can be done without reification by using KClass.isInstance
. Thats the only difference. During compile time, it doesn't matter that get
is or isn't reified when it comes to the returned type. It will always, always, always give you the same compile-time-inferred type of the KClass you passed in. The reification of get
doesn't affect that. The error you're getting, btw, is because when you do parent::class
, you get back a KClass<out Blah>
instead of a KClass<Blah>
, and so Kotlin complains because it doesn't want to use out Blah
as a reified type. I think that replacing the signature of get
to have klass: KClass<out T>
might allow you to keep it reified, but this still doesn't change the fact that it's much simpler and entirely equivalent to make get
not reified and simply just have it perform an isInstance
check inside its body.Francesc
08/23/2023, 8:16 PMinline fun <reified T : Scope> get(key: KClass<out T>): T
I'm not clear on the isInstance
part, could you share a snippet of how that'd work?Youssef Shoaib [MOD]
08/23/2023, 8:18 PMfun <T : Scope> get(key: KClass<out T>): T = (map[key] as T).also { require(key.isInstance(it) }
Francesc
08/23/2023, 8:20 PMWout Werkman
08/24/2023, 6:55 AMKClass::cast
fun <T : Scope> get(key: KClass<out T>): T = key.cast(map[key])