8

既存のメソッドの名前Extを変更すると同時に新しいメソッドを定義するという名前のトレイトを定義したいと思います。トレイトは、ケースクラスを拡張するために使用されます。私の現在の解決策はどういうわけかハッキーに見えます:equalsequalsByAttributesequals

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
    }
}

このメソッドの再実装を回避できるように、Aequalsメソッドを直接参照する方法があるのだろうか?equalsByAttributes

2012年7月12日編集

スーパー実装を参照するためのソリューションがあるので、トレイトによって拡張される基本クラス/トレイトの特定の実装にアクセスするsuper.METHOD_NAMEなど、同様の構文が必要だと思いました。これにより、私のトレイトは次のようになります。overridden.METHOD_NAMEExt

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

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

3 に答える 3

12

ケース クラスの equals を変更しないでください。そうする必要がある場合は、クラスをケース クラスにしないでください。ケースクラスのメソッドを変更すると、コードが予期しない動作をするようになり (つまり、ケースクラスとは異なり)、メンテナンスコストが増加し、ケースクラスがケースクラスのように機能すると仮定するすべてが壊れ、人々の生活が悲惨になり、多くのプログラマーがあなたの根性を嫌うようになります。 .

言い換えれば、それは価値がありません。そうしないでください。

于 2012-07-09T20:25:40.170 に答える
7

コンパイラは、既に が付属しているケース クラス(つまり、クラスを継承するか、自身で宣言するクラス) に対してはequals(およびそれぞれ) を生成しません。詳細については、このブログ エントリを参照してください。私の知る限り、あなたができる唯一のことは、 で行ったのと同じように、ケースクラスが拡張するProduct トレイトによって提供されるを使用して、構造的等価性を実装することです。hashCodeequalsproductIteratorequalsByAttributes

于 2012-07-09T13:49:13.723 に答える
0

このコードは、Ext トレイトのメソッド実装を使用します。

case class A(id: Int) extends Ext { 
  def someEqual(x:Any) = { 
    super[Ext].equalsByAttributes(x) 
  } 
}

ここでの super[X] は、このクラスが拡張する特性の 1 つを参照するために使用されます。これで 2 番目の質問に答えます。

最初の質問:

trait Ext { p: A => def eql(x:Any) = p.equals(x) }
于 2012-07-09T15:10:20.873 に答える