【发布时间】:2020-03-12 10:15:34
【问题描述】:
TL;DR
Kotlin 编译器在此处给出错误(类型不匹配):
fun <T: A()> getUtil(t: T): Util<T> = if (t is B) UtilB() else // ...
B 类的签名为:class B : A(),Util 类为class Util<T: A>,UtilB 类为class UtilB: Util<B>()。
Kotlin 编译器在此处给出警告(未经检查的强制转换):
fun <T: A()> getUtil(t: T): Util<T> = if (t is B) UtilB() as Util<T> else // ...
据我了解,Kotlin 智能演员应该知道 UtilB() as Util<T> 由 t is B 检查。
Java 代码和编译器给出完全相同的结果。
据我所知,这一定是对 Java 泛型的限制。我该如何解决这个问题?
问题描述
我有以下设置,其中一个抽象类有多个实现,而一个 util 类为每个实现提供相同的功能。
为了类型安全,我想我会创建一个抽象类Util<T: A>,并为A 的每个派生类创建另一个UtilB: Util<B> 类。
为了为每个实现获取正确的 util 类,我在伴随对象 getUtil 上创建了一个函数,它基于泛型类型 T 的参数为每个实现返回正确的 util 类,该参数扩展了 A:T: A 从而具有返回类型Util<T>。
但是,当我为A 的每个派生类编写函数体时,使用is B 检查参数的类型,然后使用UtilB() 返回正确的实用程序,Kotlin 编译器在返回点说 UtilB 不是 Util<T> 类型,即使它应该是。
然后我将 UtilB 转换为 Util<B> 并且有效,但给了我一个错误“未经检查的演员”。根据我的理解,Kotlin 智能转换应该能够确定它确实是一个有效的检查转换(使用is B 检查),并且在运行快速测试后证明它也是有效的......
我用 Java 重写了相同的代码,结果完全相同...
据我所知,这是 Java/Kotlin 泛型的限制。 我想知道如何检查这个演员表。有可能吗?
代码
这是一个最小的工作(或不工作)示例:
abstract class A
class B : A()
class C : A()
abstract class Util<T : A> {
abstract fun getName(): String
companion object {
fun <T : A> getUtil(t: T): Util<T> = when(t) {
is B -> UtilB() as Util<T> // warning
is C -> UtilC() // this event gives an error
else -> throw IllegalArgumentException("No util for this class.")
}
}
}
class UtilB : Util<B>() {
override fun getName(): String = "B"
}
class UtilC : Util<C>() {
override fun getName(): String = "C"
}
fun main() {
val b = B()
val c = C()
val utilB = Util.getUtil(b)
val utilC = Util.getUtil(c)
println(utilB.getName()) // prints B
println(utilC.getName()) // prints C
}
【问题讨论】: