4

SquerylKeyedEntityをオーバーライドする特性を定義equalsし、ifでいくつかの条件をチェックsuper.equalsし、最後に呼び出します。なので、常に失敗しますsuperObject

検討:

trait T { override def equals(z: Any):Boolean = super.equals(z)} }

case class A(a: Int) extends T

val a = A(1); val b = A(1)

a==b // false

したがって、あなたが宣言した場合

case class Record(id: Long, name: String ...) extends KeyedEntity[Long] { ... }

-そして、いくつかのRecordインスタンスを作成しますが、それらを永続化しないと、それらの比較は失敗します。Salat同じクラスの両方とSquerylバックエンドを実装することでこれを見つけましたが、 fromがfalseであるSalatため、すべてのテストが失敗します。isPersistedKeyedEntity

KeyedEntityケースクラスに混合された場合にケースクラスの同等性を維持する設計はありますか?ケースクラスタイプをPとしてセルフタイピングとパラメーター化を試みBetterKeyedEntity[K,P] { self: P => ... }ましたが、equalsで無限再帰が発生します。

現状では、オーバーライドされたequalsinの最後のブランチはsuper常にfalseを返します。ObjectKeyedEntity

4

1 に答える 1

2

equalsオーバーライドがある場合、ケースクラスに対して通常生成される構造的同等性チェックは生成されないようです。ただし、いくつかの微妙な点に注意する必要があります。

IDベースの平等の概念を構造的平等にフォールバックすることを混合することは、微妙なバグにつながる可能性があると想像できるため、良い考えではないかもしれません。例えば:

  • x: A(1)y: A(1)はまだ永続化されていないので、それらは等しい
  • その後、それらは永続化され、それらは別個のオブジェクトであるため、永続化フレームワークはそれらを別個のエンティティとして永続化する可能性があります(Squerylはわかりませんが、問題ではないかもしれませんが、これは細い線です)
  • 永続化した後、IDが異なるため、突然等しくなりません。

さらに悪いことに、xyが同じIDにhashCode永続化されると、永続化の前後で異なります(ソースは、永続化された場合、それがIDのhashCodeであることを示しています)。これは不変性を壊し、非常に悪い振る舞いにつながります(たとえばマップに配置された場合)。アサーションが失敗することを示すこの要点を参照してください。

したがって、構造的等式とIDベースの等式を暗黙的に混在させないでください。Hibernateのコンテキストで説明されているこれも参照してください。

型クラス

そのような理由で、メソッドベースの平等の概念に欠陥があることを他の人が指摘していることに注意する必要があります(2つのものが等しくなる方法は1つだけではありません)。したがって、等式を記述する型クラスを定義できます。

trait Eq[A] {
  def equal(x: A, y: A): Boolean
}

クラスのその型クラスの(場合によっては複数の)インスタンスを定義します。

// structural equality
implicit object MyClassEqual extends Eq[MyClass] { ... }

// id based equality
def idEq[K, A <: KeyedEntity[K]]: Eq[A] = new Eq[A] {
  def equal(x: A, y: A) = x.id == y.id
}

次に、物事がEq型クラスのメンバーであることを要求できます。

def useSomeObjects[A](a: A, b: A)(implicit aEq: Eq[A]) = {
  ... aEq.equal(a, b) ...
}

したがって、スコープに適切な型クラスをインポートするか、次のように型クラスインスタンスを直接渡すことで、使用する同等性の概念を決定できます。useSomeObjects(x, y)(idEq[Int, SomeClass])

Hashable同様に、型クラスも必要になる場合があることに注意してください。

Eqインスタンスの自動生成

この状況は、scala.math.OrderingScalastdlibの型クラスと非常によく似ています。これは、優れたシェイプレスライブラリを使用してケースクラスの構造インスタンスを自動派生するOrdering例です。

Eqとについても同じことが簡単にできますHashable

Scalaz

scalazにはEqualtypeclassx === yがあり、の代わりに書くことができる素敵なpimpパターンがあることに注意してくださいeqInstance.equal(x, y)。まだ型クラスがHashableあるのか​​わかりません。

于 2012-09-15T07:26:19.027 に答える