为什么当我尝试返回一个检查的generics参数的值时出现types不匹配?
在下面的代码中, "Happy Halloween!"
, 42
等被标记为“types不匹配”。 (必需:T,find:字符串(或Int)),但不应该编译器能够推断返回值types检查是正确的types?
interface Type class StringType() : Type class IntType1() : Type class IntType2(val a: Int, val b: Int) : Type fun something(type: Type): T = when (type) { is StringType -> "Happy Halloween!" is IntType1 -> 42 is IntType2 -> type.a * type.a + type.b * type.b + type.a * type.b else -> throw IllegalArgumentException() }
当编译器应用types擦除时,返回types将被定义。 所以,让我们说,你使用一个字符串…你的方法将是:
fun something(type: Type): String = when (type) { is StringType -> "Happy Halloween!" is IntType1 -> 42 //Wrong: you must return String! is IntType2 -> type.a * type.a + type.b * type.b + type.a * type.b else -> throw IllegalArgumentException() }
这个东西是: 你必须在编译时知道你的返回types 。 如果你不知道这一点,你必须告诉编译器:
fun something(type: Type ): Any = when (type) { is StringType -> "blabla" is IntType1 -> 42 is IntType2 -> type.a * type.a + type.b * type.b + type.a * type.b else -> throw IllegalArgumentException() }
对不起,这个代码不是你正在跳的,你将在返回方法后进行投射…
但是你可以这样做:
fun something(type: Type ): T = when (type) { is StringType -> type.b //is IntType1 -> 42 remove this! is IntType2 -> type.a * type.a + type.b * type.b + type.a * type.b else -> throw IllegalArgumentException() }
假设type.a和type.b被参数化为T.那么你的代码将工作得很好。
如果我简化你的例子:
interface Type fun something(type: Type ): T = when (type) { is Type -> "Happy Halloween!" else -> throw IllegalArgumentException() }
编译器现在抱怨他: cannot check for instance of erased type
所以问题在于,由于types擦除, Type
和Type
在运行时没有区别,所以编译器不会允许这样做。
你可以尝试使用像Gson的TypeToken
或jackson的TypeReference
这个文档是指这个博客文章解释这个想法: http : TypeReference
is
运算符很像Java的instanceof
运算符,在运行时执行。
所以,在编译时 ,编译器不知道实际的types,因此你会得到一个编译错误。
这是另一个简单的例子:
fun f(t: T): T { if (t is Int) return 3 // compilation error else return t }
你可以这样写:
interface Type class StringType() : Type class IntType1() : Type class IntType2(val a: Int, val b: Int) : Type inline fun something(type: Type): T { val result = when(type) { is StringType -> "Happy Halloween" is IntType1 -> 42 is IntType2 -> type.a * type.a + type.b * type.b + type.a * type.b else -> throw IllegalArgumentException() } return if (result is T) result else throw Exception() }
运行以下内容:
fun main(args: Array) { println(something(StringType())) println(something(IntType1())) println(something(IntType2(2, 3))) }
会给你这个输出:
Happy Halloween 42 19
在此了解更多关于内联函数和使用参数的信息: 实体types参数 。