1

I have the following class that acts as a base for a few other classes:

abstract class BaseFitness: Comparable<BaseFitness> { var valid: Boolean = false fun invalidate() { valid = false } abstract fun value(): Double abstract fun copy(): BaseFitness override operator fun equals(other: Any?): Boolean = if (other is BaseFitness) this.value() == other.value() else throw IllegalArgumentException("Can only compare to another class derived from BaseFitness.") override fun compareTo(other: BaseFitness): Int = this.value().minus(other.value()) .let { if (it.isNaN()) 0.0 else it } .sign.toInt() @JvmName("compareToOperator") operator fun compareTo(other: Any?): Int = if (other is BaseFitness) this.compareTo(other) else throw IllegalArgumentException("Can only compare to another class derived from BaseFitness.") } 

Now in this class I want to implement basic comparison behaviour.

Basically I want to be able to do:

  1. if (fit1 == fit2) { /* do stuff */ }

  2. if (fit1 > fit2) { /* do stuff */ }

  3. if (fit1 < fit2) { /* do stuff */ }

  4. myFitnessSequence.max()

The equals() and compareTo() operator funcs take care of the first 3 items. However for the last item I need BaseFitness to implement Comparable. Problem is that when I implement comparable and add the non-operator compareTo() method somehow equals() breaks with this message:

'operator' modifier is inapplicable on this function: must override ''equals()'' in Any 

I tried doing the same thing I did with compareTo(), just having 2 implementations of equals(), one marked as an operator and one left as a method and adding @JvmName to one of them and I get

'@JvmName' annotation is not applicable to this declaration 

Right now my options are basically to either choose to keep and == operator but not implement Comparable or give up == to use comparable.

1
  • Your equals implementation breaks the contract. It should be safe to compare it to anything (and simply return false for other types of objects). Commented Mar 2, 2020 at 16:57

1 Answer 1

2

You don't need to mark equals and compareTo with the operator keyword, both of these are already defined as operator in their respective types. In case of equals, Any defines it as operator and the compareTo is marked as operator in Comparable interface.

So all you have to do is provide their implementation by overriding them.

From Kotlin in Action

Regarding the equals method

The equals function is marked as override, because, unlike other conventions, the method implementing it is defined in the Any class (equality comparison is supported for all objects in Kotlin). That also explains why you don’t need to mark it as operator: the base method in Any is marked as such, and the operator modifier on a method applies also to all methods that implement or override it.

Regarding the Comparable interface

Kotlin supports the same Comparable interface. But the compareTo method defined in that interface can be called by convention, and uses of comparison operators ('<', '>', <=, and >=) are translated into calls of compareTo.

Sign up to request clarification or add additional context in comments.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.