Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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. 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. In Java I might give them both different identifiable names but it is fairly ugly as Kotlin extensions (e.g. a.sortA() 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.

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. I also thought about adding a comparator to every class and use Any? But that seems cumbersome as well.

like image 476
Jeremy Lyman Avatar asked Dec 10 '22 19:12

Jeremy Lyman


1 Answers

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.

Found here : https://kotlinlang.org/docs/reference/java-to-kotlin-interop.html

like image 148
Jeremy Lyman Avatar answered Dec 21 '22 22:12

Jeremy Lyman