为什么当我尝试返回一个检查的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() } 

4 Solutions collect form web for “为什么当我尝试返回一个检查的generics参数的值时出现types不匹配?”

当编译器应用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擦除, TypeType在运行时没有区别,所以编译器不会允许这样做。

你可以尝试使用像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参数 。

  • Kotlin - 在view.getTag()上的TypeCastException
  • 构造器在kotlin派生类中的可分解构造器
  • Kotlin:在unit testing中使内部函数可见
  • 接口bug中的Kotlin默认参数?
  • 修复一些Kotlin语法
  • Kotlin二级构造函数
  • Kotlin:无法从对象导入按需
  • 如何使“this”成为Listener的参考,而不是Kotlin中的Activity?
  • 为什么加号需要在行尾,而不是在下一行的开头?
  • Kotlin:使用自定义setter时没有lateinit的解决方法?
  • 我们如何在不使用第三方库的情况下在kotlin中定义id?
  • Kotlin language will be the best programming language for Android.