在case类中重命名和覆盖equals方法

时间:2012-07-09 12:35:44

标签: scala case-class

我想定义一个名为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}}方法,以便可以避免重新实现此方法?

编辑2012-07-12

由于存在一个用equalsByAttributes引用超级实现的解决方案,我认为必须有类似的语法,例如super.METHOD_NAME,用于访问将要扩展的基类/特征中的特定实现。特征,所以我的overridden.METHOD_NAME特征看起来像这样:

Ext

3 个答案:

答案 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) }