简体   繁体   English

Kotlin扩展功能按类型

[英]Kotlin extension functions by type

What is the idiomatic way to add a function to a class based on type. 基于类型向类添加函数的惯用方法是什么? The following example uses List as the class, and the Type Parameter <T> is the class of objects inside of the list. 以下示例使用List作为类,Type Parameter <T>是列表中的对象类。 Lets say you want to sort each of these lists with a different comparator based on their type. 假设您希望根据类型使用不同的比较器对每个列表进行排序。

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)
}

This gives an error saying that both sort functions have the same signatures due to Java's overloading rules. 这给出了一个错误,指出由于Java的重载规则,两个排序函数具有相同的签名。 In Java I might give them both different identifiable names but it is fairly ugly as Kotlin extensions (egasortA() b.sortB()). 在Java中,我可能会给它们两个不同的可识别名称,但它作为Kotlin扩展(egasortA()b.sortB())相当丑陋。 Kotlin doesn't show sortA to a List< B > so there seems like there would be a better way of writing sort() to handle different comparators on different objects. Kotlin没有向List <B>显示sortA,所以似乎有更好的方法来编写sort()来处理不同对象上的不同比较器。

The example is pretty simple but imagine if I don't have access to modify class A and B so I could not use inheritance or implement an interface on them. 这个例子非常简单,但想象一下,如果我没有修改类A和B的权限,那么我就无法使用继承或在它们上实现接口。 I also thought about adding a comparator to every class and use Any? 我还考虑过为每个类添加一个比较器并使用Any? But that seems cumbersome as well. 但这似乎也很麻烦。

One answer seems to be : 一个答案似乎是:

@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)
}

This seems to fix Java's issue with generic type erasure. 这似乎解决了Java与泛型类型擦除的问题。

Found here : https://kotlinlang.org/docs/reference/java-to-kotlin-interop.html 在此处找到: https//kotlinlang.org/docs/reference/java-to-kotlin-interop.html

On this site, I found this solution 在这个网站上,我找到了这个解决方案

Instead of this 而不是这个

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

Use the platformName 使用platformName

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

EDIT: This is deprecated, use JvmName instead. 编辑:这是不推荐使用的,而是使用JvmName。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM