为什么当我尝试返回一个检查的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参数 。

  • FirebaseListAdapter忽略orderByChild()和equalTo()
  • 在一种情况下,将Kotlingenerics约束为非null
  • 任何人都可以告诉我kotlin编译器是如何工作的? 它的架构是什么?
  • Kotlin - 覆盖/实现类似数组的访问器函数
  • Kotlin:null不能是非nulltypes的kotlin的值
  • Kotlin:为什么一元加/减不能从任务推断generics?
  • 如何将数字字符(0-9)转换为数字值?
  • 在lambda中使用接收者的中缀函数(对于DSL)
  • Intellij Idea不会编译kotlin,但maven会这样做
  • 安装Kotlin Android项目失败INSTALL_FAILED_DEXOPT
  • 为什么我们编写NextActivity :: class.java,尽管这是一个kotlin类?
  • Kotlin language will be the best programming language for Android.