在kotlin中,如何返回泛型类参数定义的实例

Ryb*_*yba 5 generics kotlin kotlin-extension

我正在尝试为kotlin 1.0.3的Web框架编写一个很好的Kotlin包装器.在那里我试图将一个函数混合到请求中,让它通过使用jackson的JSON转换返回一个bean.

所以在我的图书馆里,我有以下内容

private val mapper: ObjectMapper = ObjectMapper().registerModule(KotlinModule())
fun <T : Any> Request.asDataBean(type: KClass<T>): T = mapper.readValue(this.body(), type.java)
Run Code Online (Sandbox Code Playgroud)

但是当我转到使用代码时

post("/hello", { req, res ->
    val bean = req.asDataBean(TestBean::class)
})
Run Code Online (Sandbox Code Playgroud)

它错误地说bean的期望值是Any.我想要的是我的API如上所述工作,其中传递给asDataBean方法的通用"类"定义是返回的值的类型.

我也试过了

fun <T> Request.asDataBean(type: KClass<*>): T = mapper.readValue(this.body(), type.java) as T
Run Code Online (Sandbox Code Playgroud)

以及将使用代码更改为

val bean: TestBean = req.asDataBean(TestBean::class)
Run Code Online (Sandbox Code Playgroud)

希望使它工作,但他们在使用代码时也会给出完全相同的错误.

我如何使用传入的类类型定义的泛型作为参数(非常类似于所有spring api在java中的工作方式)?

mie*_*sol 5

使用具体类型参数的 Kotlin惯用方法越多:

inline fun <reified T : Any> Request.asDataBean(): T = mapper.readValue(this.body(), T::class.java)
Run Code Online (Sandbox Code Playgroud)

然后可以将其用作:

post("/hello", { req, res ->
    val bean = req.bodyAs<TestBean>()
    res.body("Ok")
})
Run Code Online (Sandbox Code Playgroud)


Ily*_*lya 5

post您的示例中的函数需要route: (Request, Response) -> Any参数,即一个函数,接受请求和响应并返回一些非空值。

当您将 lambda 表达式用作 a 时route,其返回类型是从 lambda 主体的最后一个表达式推断出来的,并且由于在 Kotlin 中赋值不是表达式,因此以下 lambda 根本没有返回类型:

{ req, res ->
    val bean = req.asDataBean(TestBean::class)
}
Run Code Online (Sandbox Code Playgroud)

为了使它工作,只需制作bean最后一个表达式

{ req, res ->
    val bean = req.asDataBean(TestBean::class)
    bean
}
Run Code Online (Sandbox Code Playgroud)

或者根本不使用赋值:

{ req, res -> req.asDataBean(TestBean::class) }
Run Code Online (Sandbox Code Playgroud)

注意:我使用了以下asDataBean函数定义:

fun <T: Any> Request.asDataBean(type: KClass<T>): T =
    mapper.readValue(this.body(), type.java)
Run Code Online (Sandbox Code Playgroud)

你也可以做一个具体化的重载,它调用非具体化的重载,这样你就不必暴露所有的内部结构:

inline fun <reified T: Any> Request.asDataBean(): T = 
    asDataBean(T::class)

req.asDataBean<TestBean>() // usage
Run Code Online (Sandbox Code Playgroud)