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?
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)
}
The compiler will not generate equals
(and hashCode
, respectively) for case classes that already come with an equals
, i.e., that inherit one or declare one themselves. Read more about this in this blog entry. AFAIK the only thing you can do is to implement structural equality by using productIterator
provided by the Product trait that case classes extend, just as you did in equalsByAttributes
.