Scala 在case类中重命名并重写equals方法
我想定义一个名为Scala 在case类中重命名并重写equals方法,scala,case-class,Scala,Case Class,我想定义一个名为Ext的trait,它将现有的equals方法重命名为equalsByAttributes,同时定义一个新的equals方法。这种特性被使用了 扩展案例类。我当前的解决方案看起来有些粗糙: case class A(id: Int) extends Ext trait Ext { p: Product => // new implementation override def equals(obj: Any) = obj match { c
Ext
的trait,它将现有的equals
方法重命名为equalsByAttributes
,同时定义一个新的equals
方法。这种特性被使用了
扩展案例类。我当前的解决方案看起来有些粗糙:
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
}
}
我想知道是否有一种直接的方法可以在equalsbytributes
中引用a
的equals
方法,从而避免重新实现该方法
编辑2012-07-12
由于有一种使用super.METHOD\u NAME
引用超级实现的解决方案,我认为必须有类似的语法,例如overrided.METHOD\u NAME
,用于访问将由trait扩展的基类/trait中的特定实现,因此,我的Ext
特征如下所示:
trait Ext { p: Product =>
override def equals(obj: Any) = ...
def equalsByAttributes(obj: Any) = overridden.equals(obj)
}
编译器不会为已经带有
equals
的case类生成equals
(分别为hashCode
),即继承一个或自己声明一个。请在中阅读更多关于此的信息。AFAIK您唯一能做的就是使用case类扩展提供的productIterator
实现结构相等,就像您在equalsByAttributes
中所做的那样。此代码将使用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) }
不要更改案例类上的等于。如果您需要这样做,不要让您的类成为案例类。改变case类方法会使代码表现出意外的行为(也就是说,与case类不同),这会增加维护成本,破坏一切假设case类像case类一样工作的东西,使人们的生活变得悲惨,并让许多程序员恨你
换句话说,这不值得。不要那样做。我测试了你的代码。不幸的是,这并不能解决问题
p.equals(x)
仍然指Ext
中的equals实现,如果equals
在Ext
中被重写。你是对的。我在推理上有个错误。不知何故,我认为case类中的equals必须在类层次结构中高于一级,因此应该可以在traitExt
中访问。但事实并非如此。这与直接在(case)类中实现equals是一样的,因此equals定义只能覆盖trait的equals定义,而不能反过来,因为超类和trait不能引用子类中的实现。顺便说一句,不必重新实现case类函数equals
、hashCode
或toString
,而可以使用Scala的原始定义:ScalaRunTime.\u equals
、ScalaRunTime.\u hashCode
和ScalaRunTime.\u toString
@StefanEndrullis如下:?下划线前缀让我有点紧张,它可能暗示了语言这一部分的易变性。好主意:-)这根本不是问题,只要我不改变equals和hasCode的预期行为。我只是想优化这些方法的性能。为此,我自动生成隐藏ID,并在equals
中进行比较,而不是在多达22个case类参数中进行比较。它只是关于运行时优化,不会破坏任何东西,也不会增加维护成本。在我的例子中,这绝对值得进行优化,因为我节省了很多不必要的比较。