I created class with generic in kotlin and want to use receive with generic, but I have error when i want to call.recieve
type from generic:
Can not use MType as reified type parameter. Use a class instead.
Code:
class APIRoute<EType : IntEntity, MType : Any> {
fun Route.apiRoute() {
post {
val m = call.receive<MType>()
call.respond(f(model))
}
}
}
How to fix it?
CodePudding user response:
You need to provide the expected type to the receive()
function. Due to type erasure in Java/Kotlin, the type of MType
is unknown at runtime, so it can't be used with receive()
. You need to capture the type as KType
or KClass
object when constructing APIRoute
.
KClass
is easier to use, however it works with raw classes only, it doesn't support parameterized types. Therefore, we can use it to create e.g. APIRoute<*, String>
, but not APIRoute<*, List<String>>
. KType
supports any type, but is a little harder to handle.
Solution with KClass
:
fun main() {
val route = APIRoute<IntEntity, String>(String::class)
}
class APIRoute<EType : IntEntity, MType : Any>(
private val mClass: KClass<MType>
) {
fun Route.apiRoute() {
post {
val m = call.receive(mClass)
call.respond(f(model))
}
}
}
Solution with KType
:
fun main() {
val route = APIRoute.create<IntEntity, List<String>>()
}
class APIRoute<EType : IntEntity, MType : Any> @PublishedApi internal constructor(
private val mType: KType
) {
companion object {
@OptIn(ExperimentalStdlibApi::class)
inline fun <EType : IntEntity, reified MType : Any> create(): APIRoute<EType, MType> = APIRoute(typeOf<MType>())
}
fun Route.apiRoute() {
post {
val m = call.receive<MType>(mType)
call.respond(f(model))
}
}
}