Home > Software design >  Ktor reified type parametar
Ktor reified type parametar

Time:11-24

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))
        }
    }
}
  • Related