鉴于我有以下代码
interface Animal {}
class Cat() : Animal {}
class Dog() : Animal {}
class MyClass<B, A : List<B>>(val list1: A, val list2: A) {}
看起来我可以像这样调用不同列表类型的构造函数:
val myClass = MyClass(listOf(Cat()), listOf(Dog()))
有没有办法指示 Kotlin 编译器两个列表应该具有相同的严格类型?
目标是我可以打电话:
val myClass = MyClass(listOf(Cat()), listOf(Cat()))
val myClass = MyClass(listOf(Dog()), listOf(Dog()))
但我不能打电话:
val myClass = MyClass(listOf(Cat()), listOf(Dog()))
val myClass = MyClass(listOf(Dog()), listOf(Cat()))
在你问之前,我需要这个的原因是我可以在
MyClass
上实现两种方法,如下所示:
class MyClass<B, A : List<B>>(val list1: A, val list2: A) {
fun moreSameAnimals(list: A) = print("same")
fun <C : List<B> moreDifferentAnimals(list: C) = print("different")
}
并让编译器根据 Animal
中存在的
MyClass
的single 类型选择适当的方法
您描述的问题是由于 Kotlin 的 type-inference 造成的。
您可以使用内置的
listOf()
函数在一个更简单的示例中看到它的工作原理。编译器根据提供给函数的值的类型推断泛型类型。
val a = listOf(3) // inferred type is List<Int>
val b = listOf("text") // inferred type is List<String>
但是,如果您提供不同类型的参数,编译器需要在参数中找到共同的supertype。所有不可空类型的统一超类型是
Any
。将可空类型添加到混合中,统一的超类型是 Any?
。
val c = listOf(3, "text") // inferred type becomes List<Any>
val d = listOf(3, "text", null) // inferred type becomes List<Any?>
在您的情况下,传递类型
Dog
和 Cat
的参数时的泛型类型将被推断为公共超类型 Animal
。