我想定义一个名为Ext
的特征,它将现有的equals
方法重命名为equalsByAttributes
,并同时定义一个新的equals
方法。使用了这个特性
扩展案例类。我目前的解决方案看起来有点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
}
}
我想知道是否有一种直接方法可以在A
中引用equals
的{{1}}方法,以便可以避免重新实现此方法?
由于存在一个用equalsByAttributes
引用超级实现的解决方案,我认为必须有类似的语法,例如super.METHOD_NAME
,用于访问将要扩展的基类/特征中的特定实现。特征,所以我的overridden.METHOD_NAME
特征看起来像这样:
Ext
答案 0 :(得分:9)
不要在案例类上更改等号。如果您需要这样做,请不要使您的类案例类。更改案例类方法将使代码行为意外(即,不同于案例类),这会增加维护成本,打破假设案例类像案例类一样工作的所有事情,使人们的生活变得悲惨并让很多程序员讨厌你的胆量
换句话说,这不值得。不要那样做。
答案 1 :(得分:7)
编译器不会为已经带有equals
的案例类生成hashCode
(和equals
),即继承一个或自己声明一个。在this blog entry中详细了解相关内容。 AFAIK唯一可以做的就是使用案例类扩展的Product trait提供的productIterator
来实现结构平等,就像在equalsByAttributes
中一样。
答案 2 :(得分:0)
此代码将使用Ext trait:
中的方法实现case class A(id: Int) extends Ext {
def someEqual(x:Any) = {
super[Ext].equalsByAttributes(x)
}
}
此处的super [X]用于指代此类扩展的特征之一。这回答了你的第二个问题。
关于你的第一个问题:
trait Ext { p: A => def eql(x:Any) = p.equals(x) }