首页 > 解决方案 > 如何解决类型不匹配要求:Foo, 发现: Foo

问题描述

给定以下 Kotlin 代码:

class Foo<T>(val t : T?)

fun <T : Any, R : Any> Foo<T?>.transform(transformer : (T) -> R) : Foo<R?> {
  return when (t) {
    null -> Foo(null)
    else -> Foo(transformer(t))
  }
}

fun main(args : Array<String>) {
  val foo = Foo(args.firstOrNull())

  val bar = foo.transform<String, Int> { t -> t.length }

  val baz = bar.transform<Int, IntRange> { t -> t..(t + 1) }
}

为什么我会收到以下错误: Type mismatch. Required: Foo<String?> Found: Foo<String>

如果我?从扩展函数中删除,Foo<T>.transform我会收到以下错误: Type mismatch. Required: Foo<Int> Found: Foo<Int?>

我可以理解第二个错误,因为您不能分配Int?Int,但第一个错误没有任何意义,因为您可以分配StringString?

编辑:

我已将其修改class Foo<T>class Foo<out T>,这对我有用,因为该值t只会在初始分配后读取。使用此选项,我不需要在transform.

我发现我认为有点混乱的另一个选项(不确定为什么会有所不同)是向扩展函数添加第三个类型参数,如下所示:

fun <T : Any, U : T?, R : Any> Foo<U>.transform(transformer : (T) -> R) : Foo<R?>

另一方面,我觉得这个呼叫站点有点奇怪。查看上面的代码,调用foo.transform 不能包含类型参数,但调用bar.transform<Int, Int?, IntRange> 必须包含类型参数才能工作。

如果它是 a而不是 ,则此选项允许t在稍后的某个时间设置该值。但它也删除了函数中的智能转换。尽管如果您不担心比赛条件或(通过一些额外的努力)或者如果您担心比赛条件,则可以解决此问题。varvalttransform!!?:?.

标签: kotlin

解决方案


您可以将您的Foo<T>类更改为不变(请参阅https://kotlinlang.org/docs/reference/generics.html):

class Foo<out T>(val t : T?)

fun <T : Any, R : Any> Foo<T?>.transform(transformer : (T) -> R) : Foo<R?> {
  return when (t) {
    null -> Foo(null)
    else -> Foo(transformer(t))
  }
}

fun main(args : Array<String>) {
  val foo = Foo(args.firstOrNull())

  val bar = foo.transform<String, Int> { t -> t.length }

  val baz = bar.transform<Int, IntRange> { t -> t..(t + 1) }
}

精确地out T指定了您想要的行为。


推荐阅读