4

これが私に頭痛の種となる特性線形化パズルゲームです。私は基本的Nodeに定義しequalshashCode他のものと比較するタイプを持っていますNode。そして、私は余分なデータと一緒にSelectorラップする可能性のあるタイプを持っているので、それ自体があり、他のデータと比較されます。NodeequalshashCodeSelector

今、私はとStandaloneを組み合わせたタイプを持っていますが、NodeSelectorに関して一貫性のない(?)線形化を取得しequalsますhashCode

trait Selector { override def hashCode = 1 }
trait Event extends Selector

trait Node { override def hashCode = 2 }
trait Standalone extends Node with Event

EventまたはStandalone:のいずれかから拡張すると、すべてが正常になります(より具体的なhashCode 1が呼び出されます) 。

object Single1 extends Event
Single1.hashCode // 1 -- ok

object Single2 extends Standalone
Single2.hashCode // 1 -- ok

この順序で両方から拡張しても問題ありません。

object Compound1 extends Standalone with Event
Compound1.hashCode // 1 -- Ok

しかし、私がこれを行うと、混乱します:

object Compound2 extends Event with Standalone
Compound2.hashCode  // 2 -- no!!!!!!!!

小さな.dot図を作成しました(ミックスインは左から右に並べられています):

ここに画像の説明を入力してください

したがって、線形化ルールを正しく理解していれば、常にhashCodeによって実装されるはずSelectorです。この振る舞いの唯一の説明は、ある種の貪欲で深さ優先の事柄が関係しているということです...?

Standaloneまた、いつでも混合されていることを確認するために使用できる手法があれば、 (コピーとからへのコピー以外の)Selectorオーバールールが確実に行われるようになります。これは非常にありがたいことです。NodeequalshashCodeSelectorStandalone

これはScala2.9.2の場合です。

4

1 に答える 1

4

この種のことについては、仕様に行くのが最善です。アルゴリズムは次の場所で説明されています。5.1.2 Class Linearization

言い換えると、クラス C の Linearization は C であり、その後に最も右の項目から拡張するものの Linearization が続きます。次に、線形化で重複を削除し、最も右側のものだけを保持する最終ステップがあります。

したがって、Compound1(AnyRefなどの組み込みを無視する)の例では:
L(Compound1) = Compound1 + L(Event) + L(Standalone)
L(Event) = Event + L(Selector)
L(Selector) = Selector
L(Standalone) = Standalone + L(Event) + L(Node)
L(Node) = Node
まとめて:
L(Compound1) = Compound1 Event Selector Standalone Event Selector Node
重複を削除します:
Compound1 Standalone Event Selector Node

最終Compound2的には次のようになります。
Compound2 Standalone Node Event Selector


Standalone他の質問に関しては、メソッドをオーバーライドして、スーパークラスで目的 のメソッドを呼び出すのが最も簡単な方法だと思います。

trait Standalone extends Node with Event { override def hashCode = super[Event].hashCode }  

これが「コピー」の意味ではないと仮定します。

于 2012-06-23T22:17:37.097 に答える