クラスSet [MyClass]の不変のSetがあり、Setメソッドのintersectとdiffを使用したいが、デフォルトのオブジェクト等価テストではなく、カスタムのequalsメソッドを使用して等価をテストしたい
==演算子をオーバーライドしようとしましたが、使用されていません。
前もって感謝します。
編集:
IntersectメソッドはGenSetLikeの具象値メンバーです
仕様: http://www.scala-lang.org/api/current/scala/collection/GenSetLike.html src: https://lampsvn.epfl.ch/trac/ scala/browser/scala/tags/R_2_9_1_final/src // library/scala/collection/GenSetLike.scala#L1
def intersect(that: GenSet[A]): Repr = this filter that
したがって、交差はフィルターメソッドを使用して行われます。
さらに別の編集:
フィルターはTraversableLikeで定義されています
仕様: http://www.scala-lang.org/api/current/scala/collection/TraversableLike.html
def filter(p: A => Boolean): Repr = {
val b = newBuilder
for (x <- this)
if (p(x)) b += x
b.result
}
私にとって不明確なのは、述語なしで呼び出されたときに使用されるものです、p。これは暗黙のパラメータではありません。
equalsとhashCodeは、定義しない場合にのみ、caseクラスで自動的に提供されます。
_case class MyClass(val name: String) {
override def equals(o: Any) = o match {
case that: MyClass => that.name.equalsIgnoreCase(this.name)
case _ => false
}
override def hashCode = name.toUpperCase.hashCode
}
Set(MyClass("xx"), MyClass("XY"), MyClass("xX"))
res1: scala.collection.immutable.Set[MyClass] = Set(MyClass(xx), MyClass(XY))
_
参照の等価性が必要な場合でも、equalsとhashCodeを書き込んで自動生成を防止し、AnyRefからバージョンを呼び出します
_ override def equals(o: Any) = super.equals(o)
override def hashCode = super.hashCode
_
それと:
_Set(MyClass("x"), MyClass("x"))
res2: scala.collection.immutable.Set[MyClass] = Set(MyClass(x), MyClass(x))
_
AnyRefから==(o: Any)
をオーバーライドすることはできません。AnyRefはシールされており、常にequalsを呼び出します。新しい(オーバーロードされた)==(m: MyClass)
を定義しようとした場合、それはSet
が呼び出すものではないため、ここでは役に立たず、一般に非常に危険です。
filter
の呼び出しに関しては、それが機能する理由は、_Set[A]
_が_Function[A, Boolean]
_であることです。そして、はい、equals
が使用されます。関数の実装(apply
)はcontains
の同義語であり、Set
のほとんどの実装は_==
_ in contains(SortedSet
は代わりにOrdering
を使用します)。そして_==
_はequals
を呼び出します。
注:MyClassをサブクラス化する場合、最初のequals
の実装は迅速でダーティであり、おそらく不適切です。もしそうなら、少なくとも型の等価性(_this.getClass == that.getClass
_)をチェックするか、canEqual
メソッドをより適切に定義する必要があります(Daniel Sobralによる このブログ を読むことができます)
.hashCode
もオーバーライドする必要があります。 .equals
は.hashCode
の安価な事前チェックとしてよく使用されるため、これは.equals
をオーバーライドする場合にほとんど常に当てはまります。等しい2つのオブジェクトは、同一のハッシュコードを持つ必要があります。デフォルトのhashCode
がカスタムの等価性に関してこのプロパティを尊重しないオブジェクトを使用していると思います、そしてSet実装はハッシュコードに基づいて仮定を行っています)。
Scala Any.equals
およびAny.hashCode
のドキュメント]を参照してください。 http://www.scala-lang.org/api/rc/scala/Any。 html
この回答は、ユーザー定義の等価性を持つカスタムの可変セットを示しています 。内部ストアをVector
に置き換え、操作ごとに自分自身の変更されたコピーを返すことで、不変にすることができます
「==を直接オーバーライドすることはできません。Anyクラスの最終メソッドとして定義されているためです。つまり、Scalaは、==をAnyクラスで次のように定義されているかのように扱います。
final def == (that: Any): Boolean =
if (null eq this) {null eq that} else {this equals that}
"Scalaのプログラミング、第2版から