有人可以帮我绕过Kotlin编译器行为吗?
该程序的目的是将输入字符串转换为相应的类型(BMsg
或CMsg
)
并在控制台中打印结果。
但是,我从编译器收到以下消息:
“类型推断失败。没有足够的信息来推断参数T ...”
import com.fasterxml.jackson.module.kotlin.jacksonObjectMapper
abstract class classA<T> {
fun handle(body: String) {
val result = convertToSpecificMessageType(body) // This line fails
printResult(result)
otherImportantStuff()
}
abstract fun otherImportantStuff()
private inline fun <reified T : Any> String.toPayloadObject(): T =
jacksonObjectMapper().readValue(this, T::class.java)
private inline fun <reified T : Any> convertToSpecificMessageType(body: String): T = body.toPayloadObject()
private fun printResult(result: T) = println("result = $result")
}
class classB : classA<BMsg>() {
override fun otherImportantStuff() = print("important stuff of class B")
}
class classC : classA<CMsg>() {
override fun otherImportantStuff() = print("important stuff of class C")
}
sealed class Msg
data class BMsg(val x: String) : Msg()
data class CMsg(val y: Int) : Msg()
fun main() {
classB().handle("{\"x\" : \"aaa\"}")
classC().handle("{\"y\" : 5}")
}
尽管我找到了一种解决方法-将convertToSpecificMessageType
方法声明为abstract
并在classB
/ classC
中覆盖,我想知道(1)是什么原因使编译器抱怨
(2)是否有一种方法可以解决该问题而不覆盖convertToSpecificMessageType
?
预先谢谢你!
PS kotlin版本='1.3.21'
答案 0 :(得分:1)
通过在方法(<reified T : Any>
和toPayloadObject
)前面声明convertToSpecificMessageType
,您将为您的方法引入一个新的类型参数T
,该参数与类型为classA
的{{1}}类型参数。
T
的方法本地声明阴影 T
上的T
。
因此,当您执行classA
时-Kotlin根本没有可用于推断其类型的上下文。尽管您使用的是val result = convertToSpecificMessageType(body)
中的方法,但是方法classA
并未使用classA的T
。
解决方案?
您不能在类上使用归一化类型,因此:
convertToSpecificMessageType
部分并将类对象传递给方法<reified T : Any>
或val result = convertToSpecificMessageType<MyType>(body)
中的方法时会提供上下文