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

Ste*_*lis 8 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
    }
}
Run Code Online (Sandbox Code Playgroud)

我不知道是否有引用一个直接的方式Aequals方法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)
}
Run Code Online (Sandbox Code Playgroud)

Dan*_*ral 9

不要在案例类上更改等于.如果您需要这样做,请不要使您的类案例类.更改案例类方法会使代码出现意外行为(也就是说,与案例类不同),这将增加维护成本,打破假设案例类像案例类一样工作的所有事情,使人们的生活变得悲惨并让很多程序员讨厌你的胆量.

换句话说,它不值得.不要那样做.

  • 这根本不是问题,只要我不改变equals和hasCode的预期行为.我只想优化那些有关性能的方法.我自动生成隐藏的id,我在`equals`中比较,而不是最多22个case类参数.它只是关于运行时优化,它不会破坏任何东西,也不会增加维护成本.在我的情况下,进行这种优化绝对值得,因为我节省了大量不必要的比较. (2认同)

Mal*_*off 7

编译器不会生成equals(和hashCode分别)已经带有a的case类equals,即继承一个或自己声明一个.在此博客条目中阅读更多相关信息.AFAIK唯一可以做的就是通过使用productIterator由案例类扩展的Product特征来实现结构相等,就像你在做的那样equalsByAttributes.

  • 顺便说一句,不用重新实现 case 类函数 `equals`、`hashCode` 或 `toString`,可以使用 Scala 的原始定义:`ScalaRunTime._equals`、`ScalaRunTime._hashCode` 和 `ScalaRunTime._toString`。 (2认同)