kotlin - 如何解决类型不匹配要求: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
,但第一个错误没有任何意义,因为您可以分配String
给String?
编辑:
我已将其修改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
在稍后的某个时间设置该值。但它也删除了函数中的智能转换。尽管如果您不担心比赛条件或(通过一些额外的努力)或者如果您担心比赛条件,则可以解决此问题。var
val
t
transform
!!
?:
?.
解决方案
您可以将您的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
指定了您想要的行为。
推荐阅读
- mysql - 在node express中根据mysql数据库中的角色值实现用户角色
- vim - 增加或减少数字同时
和 Cx> 绑定在 vim 中未映射 - javascript - 如何在 Spark AR 的脚本编辑器中将纹理应用到材质
- ruby-on-rails - 如何从错误中读取 Rails 验证?
- python - 在函数定义中为返回类型添加换行符
- excel - 将 .xlsx 文件的每一行保存到 .txt
- node.js - 有没有办法从 NodeJs 中未等待的承诺中抛出错误?
- linux - 如何在程序运行到 xxd 时通过管道输出程序?
- python - Python:是否可以根据比例为箱线图点着色,而不是用于箱线图本身?
- reactjs - 渲染属性或 null