What is the best pattern for where to implement eq...
# getting-started
m
What is the best pattern for where to implement equals/hashCode/toString in a class hierarchy where there is one interface with many implementing classes? I would like to define this in one place (because in this case the implementations would be the same for all classes). Kotlin doesn’t allow to define them on the interface. The obvious solution is have a single base class that all other classes extend from, but then that base class cannot be private (because other implementing classes are public) and what if a class is already extending a class.
s
all right, here’s a cursed but somewhat functional idea — declare
equals
and
hashCode
in the interface, have an internal abstract class implement the interface, have implementing classes implement the interface via delegation
Copy code
import java.util.Objects

interface Foo {
  val a: Int
  val b: Int
  val c: Int
  override fun equals(other: Any?): Boolean
  override fun hashCode(): Int
}

internal abstract class AbstractFoo(
    override val a: Int,
    override val b: Int,
    override val c: Int) : Foo {
  override fun equals(other: Any?): Boolean {
    print("wow! ")
    return other is Foo && other.a == a && other.b == b
  }

  override fun hashCode(): Int = Objects.hash(a, b)
}

class BarFoo : Foo by object : AbstractFoo(1,2,3) {}
class BazFoo : Foo by object : AbstractFoo(1,2,4) {}

val barFoo: Foo = BarFoo()  // not sure why one needs to be annotated as Foo
val bazFoo = BazFoo()

println(barFoo == bazFoo)  // prints "wow! true"
disclaimer: don’t do this, I’m not sure where the pitfalls lie in an implementation like this and I’m sure it’ll confuse the hell out of your coworkers if they saw fragments of this out in the wild (plus that equals issue is odd)
m
At the moment, I define internal extension funs like
fun MyInterface.hashCode() =…
and then in each class have something like
override fun hashCode() = defaultHashCode()
Probably should make them inline?