generics - Kotlin - "where"通用约束问题

标签 generics kotlin

ClassAClassB,还有如下函数:

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
    }
}

现在,由于 ClassAClassB 之间没有任何共同点,因此可以推断出 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/

相关文章:

特定基类的 C++ 类模板

rx-java - 如何使用 RxJava 和 Kotlin 进行 groupBy 和收集?

java - Kotlin Mockito 总是返回作为参数传递的对象

kotlin - 我无法理解 Kotlin 中的 generateSequence 函数

kotlin - 在 Kotlin 中进行空检查的最佳方法?

java - 为什么 Dagger 图可以在 java 中工作,但在 Kotlin 中却说在我提供时缺少提供?

java - 泛型 List<String> 和 List<Integer> 未按预期运行

c# - Entity Framework Core DbContext.RemoveRange 和类型约束

java - 仅限消费者的 kotlin 泛型

c# - 替代使用标记接口(interface)来测试派生泛型类?