kotlincomparableextension-function

What is the difference between Comparable and operator compareTo?


Lets say I have class A(val foo: Double).

I want to be be able to compare it to other A, Double, and Int.

If I implement Comparable, I can only compare it against one other object type.

override fun compareTo(other: A): Int {
        return when {
            this.foo == other.foo -> 0
            this.foo > other.foo -> 1
            else -> -1
        }
    }

But I've also seen extension functions overriding the compareTo operator.

operator fun A.compareTo(d: Double): Int {
    return when {
        this.foo == d -> 0
        this.foo > d -> 1
        else -> -1
    }
}

What is the difference between these and what should I be using? I'm guessing if I want to compare it to multiple types then I have to use extension functions?


Solution

  • Comparable is a standard interface, it's the way you define a class as having some ordering, and every library that deals with ordering works with Comparable types. Basically, if you want to be able to order and compare your things using all the standard functions and anything anyone else might write, you need to implement the Comparable interface.

    This works:

    data class SportsTeam(val name: String) : Comparable<SportsTeam> {
        override fun compareTo(other: SportsTeam): Int = when {
            name == "best team" -> 1
            other.name == "best team" -> -1
            else -> 0
        }
    }
    
    fun main(args: Array<String>) {
        val best = SportsTeam("best team")
        val worst = SportsTeam("worst team")
        print("The winner is: ${maxOf(best, worst).name}")
    }
    

    but because maxOf takes a Comparable type, this won't work:

    data class SportsTeam(val name: String)
    
    fun SportsTeam.compareTo(other: SportsTeam): Int = when {
        name == "best team" -> 1
        other.name == "best team" -> -1
        else -> 0
    }
    
    fun main(args: Array<String>) {
        val best = SportsTeam("best team")
        val worst = SportsTeam("worst team")
        print("The winner is: ${maxOf(best, worst).name}")
    }