提问人:Crigges 提问时间:6/19/2023 更新时间:6/19/2023 访问量:58
为什么在我的通用 Kotlin 函数中未选中此强制转换?
Why is this cast in my generic Kotlin function unchecked?
问:
看看这个MVCE:
abstract class Bar
class BarHolder(val barFunctor : Bar.()-> Unit)
fun <T : Bar>foo(bar: T.() -> Unit) {
val activeRequest = BarHolder(bar as (Bar.() -> Unit))
}
强制转换标记为未选中。但是我想不出强制转换在运行时失败的情况,因为始终是 的子类,不是吗?bar as (Bar.() -> Unit)
T
Bar
我知道我可以通过添加来忽略它,但这对我来说似乎很糟糕。那么,避免不安全铸件的正确方法是什么呢?@Suppress("UNCHECKED_CAST")
有关更多上下文,预期的用例如下所示:
class LongBar : Bar()
val length = 69
fun foobar(){
foo<LongBar>(){
println(length)
}
}
答:
4赞
broot
6/19/2023
#1
您的代码不是类型安全的,而 Kotlin 是正确的,它不应该被允许。
问题在于,例如,您可能有一个非常特定类型的 的消费者,然后将其转换为任何对象的消费者。如果随后使用这个使用者并将对象传递给它,该怎么办?Bar
Bar1
Bar
Bar1
Bar2
fun main() {
val bar1Consumer: Bar1.() -> Unit = { toString() }
val holder = foo(bar1Consumer)
holder.barFunctor.invoke(Bar2()) // ClassCastException
}
fun <T : Bar>foo(bar: T.() -> Unit) = BarHolder(bar as (Bar.() -> Unit))
class Bar1 : Bar()
class Bar2 : Bar()
很难与您的真实示例相关联,因为我们不知道 中到底发生了什么,但请注意,在未经检查的投射之后,这是允许的,并且会抛出:foo()
ClassCastException
val activeRequest = BarHolder(bar as (Bar.() -> Unit))
activeRequest.barFunctor.invoke(IntBar())
评论
0赞
Crigges
6/19/2023
我花了一些时间,但现在有意义了。我的错误是孤立地看待函数,而不考虑调用部分。由于调用部分在我的程序中位于完全不同的位置。foo
1赞
gdomo
6/19/2023
下面的解释也是有道理的:由于 T 是 Bar 的子类,那么可以是在子类中定义的函数,而不是在 Bar 类中存在的函数。因此,您不能将其作为 a 传递,因为在通用类 Bar 的对象中不能有 by 函数表示。bar: T.() -> Unit
Bar.()-> Unit
bar
评论