8

我想定义一个名为的特征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'sequals方法的方法,equalsByAttributes以便避免重新实现该方法?

编辑 2012-07-12

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

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

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

3 回答 3

12

不要更改 case 类上的 equals。如果您需要这样做,请不要让您的课程成为案例课程。更改案例类方法会使代码表现出意外(即与案例类不同),这将增加维护成本,破坏假设案例类像案例类一样工作的一切,使人们的生活变得悲惨,并让很多程序员讨厌你的胆量.

换句话说,这不值得。不要那样做。

于 2012-07-09T20:25:40.170 回答
7

编译器不会为已经带有 的案例类生成equals(和,分别) ,即继承一个或自己声明一个。在此博客条目中阅读有关此内容的更多信息。AFAIK 你唯一能做的就是通过使用案例类扩展的Product trait提供的实现结构相等,就像你在.hashCodeequalsproductIteratorequalsByAttributes

于 2012-07-09T13:49:13.723 回答
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) }
于 2012-07-09T15:10:20.873 回答