为什么在我的通用 Kotlin 函数中未选中此强制转换?

Why is this cast in my generic Kotlin function unchecked?

提问人:Crigges 提问时间:6/19/2023 更新时间:6/19/2023 访问量:58

问:

看看这个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)TBar

我知道我可以通过添加来忽略它,但这对我来说似乎很糟糕。那么,避免不安全铸件的正确方法是什么呢?@Suppress("UNCHECKED_CAST")

有关更多上下文,预期的用例如下所示:

class LongBar : Bar()
    val length = 69

fun foobar(){
    foo<LongBar>(){
        println(length)
    }
}
Kotlin 泛型转换

评论

0赞 AndrewL 6/19/2023
这与擦除有关。但是我没有解决方案,对不起

答:

4赞 broot 6/19/2023 #1

您的代码不是类型安全的,而 Kotlin 是正确的,它不应该被允许。

问题在于,例如,您可能有一个非常特定类型的 的消费者,然后将其转换为任何对象的消费者。如果随后使用这个使用者并将对象传递给它,该怎么办?BarBar1BarBar1Bar2

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.() -> UnitBar.()-> Unitbar