Kotlin 中的严格泛型

问题描述 投票:0回答:1

鉴于我有以下代码

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 generics type-inference
1个回答
0
投票

您描述的问题是由于 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

© www.soinside.com 2019 - 2024. All rights reserved.