如何限制通用扩展功能参数类型?

时间:2019-12-08 03:46:45

标签: generics kotlin extension-function

我尝试使用列表扩展功能binarySearch

public fun <T> List<T>.binarySearch(element: T, comparator: Comparator<in T>,
fromIndex: Int = 0, toIndex: Int = size): Int

这是我的定义:

open class Z
open class ZZ : Z()
open class ZZZ : ZZ()
open class ZZZZ : ZZZ()

val list: List<ZZZZ> = listOf()
val a0 = list.binarySearch("text", stringComparator) <-- error
val a1 = list.binarySearch("text", anyComparator)
val a2 = list.binarySearch(Z(), zComparator)
val a3 = list.binarySearch(ZZ(), zzComparator)
val a4 = list.binarySearch(ZZZ(), zzzComparator)

val stringComparator = Comparator<String> { o1, o2 -> o1.length.compareTo(o2.length) }
val anyComparator = Comparator<Any> { o1, o2 -> o1.hashCode().compareTo(o2.hashCode()) }
val zComparator = Comparator<Z> { o1, o2 -> o1.hashCode().compareTo(o2.hashCode()) }
val zzComparator = Comparator<ZZ> { o1, o2 -> o1.hashCode().compareTo(o2.hashCode()) }
val zzzComparator = Comparator<ZZZ> { o1, o2 -> o1.hashCode().compareTo(o2.hashCode()) }

binarySearch函数不能接受String类型,但可以接受ZZZZ的超类型。我认为第一个参数只接受ZZZZ类型,因为定义了List ,但是为什么它可以接受所有ZZZZ的超类型?

更新:

我创建一个列表扩展功能,如下所示:

fun <T> List<T>.ccc(t: T): Boolean {
    return contains(t)
} 

val list = listOf<ZZZZ>()
list.ccc("Q")
list.ccc(0)
list.ccc(mutableListOf<String>())
list.ccc(Z())
list.ccc(ZZ())
list.ccc(ZZZ())

我发现它可以接受多种类型,相关的问题是这样的: How to write strongly typed generic extension function in Kotlin?

binarySearch()功能是否与ccc()相同?

为什么ccc()不仅可以接受ZZZZ的超类型,还可以接受其他类型?

再次感谢您的帮助!

1 个答案:

答案 0 :(得分:0)

因为List是协变的,所以List<ZZZZ>也是List<Z>List<Any>等。因此在a1a4的情况下有一个合适的T可以推断出来并且可以编译。

如果您真的想要避免这种情况,则可以创建一个不变式包装器

class InvariantList<T>(val x: List<T>)

public fun <T> InvariantList<T>.binarySearch(element: T, comparator: Comparator<in T>, fromIndex: Int = 0, toIndex: Int = size): Int = x.binarySearch(element, comparator, fromIndex, toIndex)

val list: InvariantList<ZZZZ> = InvariantList(listOf())

现在

val a0 = list.binarySearch("text", stringComparator)
val a1 = list.binarySearch("text", anyComparator)
val a2 = list.binarySearch(Z(), zComparator)
val a3 = list.binarySearch(ZZ(), zzComparator)
val a4 = list.binarySearch(ZZZ(), zzzComparator)

全部将无法编译。