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必须在类层次结构中高于一级,因此应该可以在trait
Ext
中访问。但事实并非如此。这与直接在(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类参数中进行比较。它只是关于运行时优化,不会破坏任何东西,也不会增加维护成本。在我的例子中,这绝对值得进行优化,因为我节省了很多不必要的比较。