【问题标题】:How to restrict the generic extension function parameter type?如何限制泛型扩展函数参数类型?
【发布时间】:2019-12-08 03:46:45
【问题描述】:

我尝试使用列表扩展函数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的超类型,还可以接受其他的?

再次感谢您的帮助!

【问题讨论】:

    标签: generics kotlin extension-function


    【解决方案1】:

    因为List 是协变的,所以List&lt;ZZZZ&gt; 也是List&lt;Z&gt;List&lt;Any&gt; 等。所以在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)
    

    所有将无法编译。

    【讨论】:

    • 感谢您的回答,我更新了一个相关问题,您能帮我理解一下吗?谢谢!
    • 因为 List 是协变的,我认为 list 只接受它自己和它的子类型,不是吗?
    • 我说你答案的第一行,“因为List是协变的”,所以List只能是T类扩展ZZZZ的list,我的理解正确吗?
    • 协变意味着List&lt;B&gt;List&lt;A&gt; 的子类型,而BA 的子类型。所以List&lt;some subtype of ZZZZ&gt;List&lt;ZZZZ&gt; 的子类型,反之则不然。
    猜你喜欢
    • 2021-06-27
    • 2023-03-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-07-24
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多