7

Is it possible to write default implementation of equals method in a Kotlin interface?

I have this code:

interface User {

  val id: String

}

And I want all the classes implementing User to being compared using id property. Something like this:

interface User {

  val id: String

  fun equals(other: Any?) : Boolean {
    //check type and stuff
    return id == other.id
  }

}

I know I can (and maybe should) use an abstract class, but I have to deal with this scenario now.

Thank you

Héctor
  • 24,444
  • 35
  • 132
  • 243

1 Answers1

8

No, I'm afraid that's not possible.

If you try your code, the compiler complains that:

        'equals' hides member of supertype 'Any' and needs 'override' modifier

And if you add the override modifier:

        An interface may not implement a method of 'Any'

The reasons are a bit obscure, and are inherited (!) from Java.

Originally, interfaces could only contain abstract methods (and constant fields).  When the ability to specify method implementations in interfaces was added, it was done in a way so as not to break existing code, so they only apply where classes don't already have an implementation.  (In Java they're called ‘default’ methods to reinforce that.)  If a class has an implementation, either defined within the class or in a superclass, that gets used, and the default is ignored.

There are a few corner cases, though: the methods defined in Object (Java's equivalent of Kotlin's Any).  Those are clone(), equals(), finalize(), getClass(), hashCode(), notify(), notifyAll(), toString(), and wait().  (Most of those are rarely used directly these days, but of course equals(), hashCode(), and toString() are very important.)

Because those methods are defined in Object, every class has a direct implementation of them (either from Object or some subclass).  And so the interface's default implementation can never be used.

Exactly the same applies to Kotlin/JVM and the corresponding methods defined in Any — in fact, the compiler makes it explicit by giving an error if you try to provide a default implementation of any of those methods, as shown above.

This is a shame, because there are cases where a default implementation of equals(), hashCode(), and/or toString() would be extremely useful!  But it would introduce complexity, fragility, and some surprising corner cases; see this answer for an authoritative explanation.

gidds
  • 16,558
  • 2
  • 19
  • 26