【问题标题】:Kotlin extension functions by typeKotlin 扩展函数(按类型)
【发布时间】:2016-01-09 02:59:02
【问题描述】:

根据类型将函数添加到类的惯用方法是什么。以下示例使用 List 作为类,类型参数<T> 是列表内的对象类。假设您想根据它们的类型使用不同的比较器对这些列表中的每一个进行排序。

data class A(val foo: String)
data class B(val bar: Int)

private val aComparator: Comparator<A> = Comparator { lhs, rhs -> rhs.foo.compareTo(lhs.foo) }
private val bComparator: Comparator<B> = Comparator { lhs, rhs -> rhs.bar.compareTo(lhs.bar) }

fun <T: A> List<T>.sort(): List<T> {
    return this.sortedWith<T>(aComparator)
}

fun <T: B> List<T>.sort(): List<T> {
    return this.sortedWith<T>(bComparator)
}

这给出了一个错误,指出由于 Java 的重载规则,两个排序函数具有相同的签名。在 Java 中,我可能会给它们两个不同的可识别名称,但它作为 Kotlin 扩展(例如 a.sortA() b.sortB())相当难看。 Kotlin 不会将 sortA 显示给 List,因此似乎有更好的方法来编写 sort() 来处理不同对象上的不同比较器。

这个例子非常简单,但想象一下,如果我无权修改 A 类和 B 类,那么我就不能使用继承或在它们上实现接口。我还考虑为每个类添加一个比较器并使用 Any?但这似乎也很麻烦。

【问题讨论】:

    标签: kotlin kotlin-extension


    【解决方案1】:

    一个答案似乎是:

    @JvmName("sortA")
    fun <T: A> List<T>.sort(): List<T> {
        return this.sortedWith<T>(aComparator)
    }
    
    @JvmName("sortB")
    fun <T: B> List<T>.sort(): List<T> {
        return this.sortedWith<T>(bComparator)
    }
    

    这似乎解决了 Java 的泛型类型擦除问题。

    在这里找到:https://kotlinlang.org/docs/reference/java-to-kotlin-interop.html

    【讨论】:

    • 它不完全是“通用类型擦除”。 Kotlin 可以在编译时区分这两个函数,因为它的签名包括泛型,并且还可以通过返回类型来区分。 Java 不使用泛型类型创建方法签名。因此,这会更改字节码中的实际方法名称,重命名它,以便现在有两个独立的方法,不再需要通过签名来区分。而不是一个具有明显相同签名的类上的两个重载函数。
    【解决方案2】:

    On this site, I found this solution

    不是这个

    fun Iterable<Long>.average(): Double {}
    fun Iterable<Int>.average(): Double {}
    

    使用平台名称

    fun Iterable<Long>.average(): Long {
    }
    platformName("averageOfInt") fun Iterable<Int>.average(): Int {
    }
    

    编辑:已弃用,请改用 JvmName。

    【讨论】:

    • 此示例使用过时的 Kotlin 语法,不再与当前版本兼容。上面 Jeremy 的回答显示了使用最新语法的相同解决方案。
    • platformName 已弃用(或现在已删除),JvmName 是最新的。更新到 Kotlin 1.0 测试版并观察您的编译器警告/错误。
    猜你喜欢
    • 1970-01-01
    • 2019-03-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多