generics - Kotlin 中的逆变

标签 generics kotlin contravariance

我从来没有真正理解 Java 中的泛型,所以 Kotlin 似乎就是这种情况。考虑以下代码片段(这是一个人为的示例):

class AnyComparator: Comparator<Any> {
    override fun compare(o1: Any, o2: Any): Int {
        TODO("not implemented")
    }
}


fun <T> test() {
    val x: Comparator<in Double> = AnyComparator() // OK!
    val y: Comparator<in T> = AnyComparator() // Compilation error
}

第二次分配失败并出现错误

Type mismatch. 
Required: kotlin.Comparator<in T>
Found: AnyComparator

现在,如果我理解正确 in 修饰符表示 T 仅由泛型类型 Comparator 消耗(它使逆变),所以我应该能够为任何 Comparator 分配类型参数 E,它是 T 的基类。基于此,我应该能够将 AnyComparator 分配给两个变量 xy,因为类型 Any是 Kotlin 中每个类的基类。事实证明我不能,我不明白为什么。

最佳答案

这可能看起来很奇怪,但是 Any不是所有 kotlin 类的父类(super class),而只是不可为空的类。所有 Kotlin 类的真正父类(super class)是 Any? (它也是 Any 的父类(super class))。

泛型 T在您的test函数没有上限,所以它可以是一个可以为空的对象 Any? .错误是因为你不能 Comparator<Any>当您需要 Comparator<Any?> .

因此您可以修复定义 T 的示例上限为 Any :

fun <T: Any> test() {
    //...
}

关于generics - Kotlin 中的逆变,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44861928/

相关文章:

android - 将数据传递给 Intent/BroadcastReceiver

java - 如何在 Kotlin 中创建类的实例并重写其函数?

c# - 参数必须是输入安全错误

scala - 为什么Scala编译器说逆变类型A出现在类型> : A <: Any of type B?的协变位置

c# - 我们可以有一个返回类型与输入参数类型相同的泛型函数吗?

java - 如何对 List 的每个元素执行操作并返回结果(当然不影响原始结果)?

c# - 带有通用接口(interface)的 NInject

android - 带过滤器的自定义 ArrayAdapter 未正确过滤

java逆变疑问

scala - 如何在不发出警告的情况下匹配未知的泛型类型