Rename and Override equals method in case class

Stefan Endrullis picture Stefan Endrullis · Jul 9, 2012 · Viewed 9.7k times · Source

I want to define a trait named Ext that renames the existing equals method to equalsByAttributes and defines a new equals method at the same time. The trait is used to extend case classes. My current solution looks somehow hacky:

case class A(id: Int) extends Ext

trait Ext { p: Product =>
    // new implementation
    override def equals(obj: Any) = obj match {
        case that: AnyRef => this eq that
        case _ => false
    }

    // reimplementation of old equals implementation
    def equalsByAttributes(obj: Any) = obj match {
        case that: Product =>
            if (this.getClass.isAssignableFrom(that.getClass) || that.getClass.isAssignableFrom(this.getClass))
                p.productIterator.toList == that.productIterator.toList
            else
                false
        case _ => false
    }
}

I wonder if there is a direct way to reference A's equals method in equalsByAttributes so that one can avoid the reimplementation of this method?

Edit 2012-07-12

Since there is a solution for referencing super implementations with super.METHOD_NAME I thought there must be a similar syntax such as overridden.METHOD_NAME for accessing specific implementations in the base class/trait that is going to be extended by the trait, so that my Ext trait would look like this:

trait Ext { p: Product =>
    override def equals(obj: Any) = ...

    def equalsByAttributes(obj: Any) = overridden.equals(obj)
}

Answer

Daniel C. Sobral picture Daniel C. Sobral · Jul 9, 2012

Do not change equals on case classes. If you need to do so, do not make your classes case classes. Changing case class methods will make the code behave unexpectedly (that is, unlike case classes), which will increase maintenance cost, break everything that assumes case classes work like case classes, make people's life miserable and get a lot of programmers to hate your guts.

In other words, it's not worth it. Don't do that.