有ClassA
和ClassB
,还有如下函数:
fun <T> doSomething(arg: T) where T: ClassA, T: ClassB { }
当我调用此函数并将类 ClassC 的对象作为参数传递时,它编译完美并按预期工作:
class ClassC: ClassA(), ClassB
但是当我有一个 Any
类型的对象并执行如下操作时:
if (arg is ClassA && arg is ClassB) {
doSomething(arg)
}
编译器不编译它并说
None of the following functions can be called with the arguments supplied
我原以为 smart-cast 应该可以完成这项工作,但事实并非如此。请告诉我怎么了。提前致谢。
最佳答案
智能转换工作,只是不是您期望的那样。
为了帮助您理解,您的支票:
if (arg is ClassA && arg is ClassB) {
doSomething(arg)
}
翻译成:
if (arg is ClassA) {
if (arg is ClassB) {
doSomething(arg) // Only what's common between ClassA and ClassB is there
}
}
现在,由于 ClassA
和 ClassB
之间没有任何共同点,因此可以推断出 Any
。这不是您所期望的。
你当然可以强制转换:
if (arg is ClassA && arg is ClassB) {
doSomething(arg as ClassC)
}
但这也可能行不通:
class ClassC: ClassA(), ClassB
class ClassD: ClassA(), ClassB // This will cause ClassCast exception
最后,使用这种类型的约束只有在这种情况下才有意义:
open class ClassC: ClassA(), ClassB
class ClassD: ClassC()
class ClassE: ClassC()
现在,问题是为什么要推断出 Any
。不应该是 Nothing
,因为没有任何共同点吗?
这里我们需要记住 Kotlin 类型系统是如何工作的。
如果你这样写:
open class ClassA
open class ClassB
你的实际意思是:
open class ClassA : Any
open class ClassB : Any
这就是我们推断的共同祖先。
另一方面,Nothing
是位于类层次结构底部的最终类。所以没有一个类可以从它继承。
关于generics - Kotlin - "where"通用约束问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57490107/