Rob Elliot
02/26/2021, 2:52 PMRuckus
02/26/2021, 3:27 PMZach Klippenstein (he/him) [MOD]
02/26/2021, 3:40 PMZach Klippenstein (he/him) [MOD]
02/26/2021, 3:40 PMYoussef Shoaib [MOD]
02/26/2021, 3:55 PMTypeWrapper
and then I have only one instance of it which has Nothing for all the type params, then I have functions that "construct" a TypeWrapper
named type
that basically just return that one instance, but basically this forces the compiler to carry that type information around. Then, I make my functions either extensions on TypeWrapper or take in a parameter of it and then use its type params. I realise that this is very hard to explain in text so just give me one second and I'll find my like 100 line code with all the definitions and demonstration of how it works, but tbh it is a very neat trick that does the jobYoussef Shoaib [MOD]
02/26/2021, 4:15 PMsealed class TypeWrapper<out T1, out T2> {
@PublishedApi internal object Impl: TypeWrapper<Nothing, Nothing>()
}
inline fun <T1, T2> type(): TypeWrapper<T1, T2> = TypeWrapper.Impl
and now, for the most important piece of all, this is how the callsite looks like (playground):
inline fun <reified T1, T2, reified R> TypeWrapper<T1, T2>.myFun(param1: Any, param2: R): String = param1.toString() + param2 + T1::class + R::class
fun main() {
println(type<Int, Boolean>().myFun("Hello", " World"))
}
or alternatively if you already have an extension receiver (playground):
inline fun <reified T1, T2, reified R> Any.myFun(param2: R, type: TypeWrapper<T1, T2>): String = toString() + param2 + T1::class + R::class
fun main() {
println("Hello".myFun(" World", type<Int, Boolean>()))
}
sealed class TypeWrapper<out T1, out T2> {
@PublishedApi internal object Impl: TypeWrapper<Nothing, Nothing>()
}
inline fun <T1, T2> type(): TypeWrapper<T1, T2> = TypeWrapper.Impl
Rob Elliot
02/26/2021, 4:20 PM