Search code examples
scalaextension-methodsimplicitscala-3

Is it possible in Scala 3 overriding a method in superclass with extension methods?


I tried to override the equals method of java.lang.Object by doing this:

  extension(cellTower: CellTower)
    // CellTower class unfortunately has no equals() implementation, 
    // but a toString(), so we use this for equality
    def equals(other: Object): Boolean = cellTower.toString == other.toString

It didn't get used for equality (==).

Is this impossible with Scala 3 extension methods or am I doing something wrong?


Solution

  • This is not possible: Object already has the method equals, all reference types extend Object, so the compiler will always take the overridden java.lang.Object.equals, and never look for any extension methods.

    A more complete version of your example would look a little bit like this:

    case class Foo(a: Int, b: String):
      override def toString = b
    
    extension (foo: Foo)
      def equals(other: AnyRef): Boolean = foo.toString == other.toString
    
    val u = Foo(42, "x")
    val v = Foo(58, "x")
    
    println(u.toString == v.toString) // true
    println(u == v) // false
    
    

    What you could do however, is to use your own implementation of Eq with ===:

    import cats.kernel.Eq
    import cats.syntax.eq._
    
    case class Foo(a: Int, b: String):
      override def toString = b
    
    object Foo:
      given Eq[Foo] with
        def eqv(x: Foo, y: Foo): Boolean = x.b == y.b
    
    val u = Foo(42, "x")
    val v = Foo(58, "x")
    
    println(u.toString == v.toString) // true
    println(u == v)                   // false
    println(u === v)                  // true
    

    Same applies to toString -> Show and hashCode -> Hash (link to scaladoc for cats.kernel.Hash). Whenever you need more control over equality / hashing / string-representation, consider using the corresponding type classes instead.