2012-03-27 4 views
1

セッションで直列化および逆直列化されるクラスがあり、内部クラスでパターンマッチングを実行する必要があります。シリアル化でのオブジェクトのアイデンティティ/パターンマッチングの修正

class Tree(val id: Int) { 
    override def hashCode = id 
    override def equals(that: Any) = that.isInstanceOf[Tree] && 
    that.asInstanceOf[Tree].id == id 

    case object EmptyValue 
} 

val t1 = new Tree(33) 
val t2 = new Tree(33) 

t1 == t2 // ok 
t1.EmptyValue == t2.EmptyValue // wrong -- reports 'false' 

いわば「パスの依存関係をエスケープ」しないようにEmptyValueのためのアイデンティティを修正するエレガントな方法は何ですか:私は内部クラスのアイデンティティの問題を抱えています。私は、シリアル化が行われている時に壊れ、次のようなコードを持っている:

コンパイラは、私はシリアル化を使用した場合、ランタイム MatchErrorを取得し、私のマッチ が網羅あると言うが、ある
def insert(point: Point, leaf: Leaf): Unit = { 
    val qidx = hyperCube.indexOf(point) 
    child(qidx) match { 
    case EmptyValue => ... 
    ... 
    } 
} 

(私は、カスタムコードを持っていますそのバイト配列からの書き込み/読み込み)たとえば、[email protected]のツリー内から呼び出して、[email protected]を取得していて、一致しません。

EDIT

彼らは型パラメータを持っているので、すべてのパターンマッチングコードを分割する必要がありますように私は本当に、うちの内側の種類を移動することを避けるためにたいと思いますので、私は、さらにテストを行いました。

class Tree { 
    sealed trait LeftChild 
    case object EmptyValue extends LeftChild 
    sealed trait LeftNonEmpty extends LeftChild 
    final case class LeftChildBranch() extends LeftNonEmpty 

    def testMatch1(l: LeftChild) = l match { 
    case EmptyValue  => "empty" 
    case LeftChildBranch() => "non-empty" 
    } 

    def testMatch2(l: LeftChild) = l match { 
    case EmptyValue  => "empty" 
    case n: LeftNonEmpty => "non-empty" 
    } 
} 

val t1 = new Tree 
val t2 = new Tree 

t1.testMatch1(t2.LeftChildBranch().asInstanceOf[t1.LeftChild])  // works!!! 
t1.testMatch2(t2.LeftChildBranch().asInstanceOf[t1.LeftChild])  // works!!! 
t1.testMatch1(t2.EmptyValue.asInstanceOf  [t1.EmptyValue.type]) // fails 

答えて

2

存在型はこれを表現することができます。

scala> case class Tree(id: Int) { 
    | case object EmptyValue { 
    |  override def hashCode = 0 
    |  override def equals(that: Any) = that.isInstanceOf[x.EmptyValue.type forSome { val x: Tree }] 
    | } 
    | } 
defined class Tree 

scala> val t1 = Tree(33) 
t1: Tree = Tree(33) 

scala> val t2 = Tree(33) 
t2: Tree = Tree(33) 

scala> t1.EmptyValue == t2.EmptyValue 
res0: Boolean = true 

equalsためのバイトコード:

scala> :javap -v Tree.EmptyValue 

... 
public boolean equals(java.lang.Object); 
    Code: 
    Stack=1, Locals=2, Args_size=2 
    0: aload_1 
    1: instanceof #23; //class Tree$EmptyValue$ 
    4: ireturn 
... 
+0

それは素晴らしいユージンです。 'equals'のこの定義がある種のランタイムペナルティ(' isInstanceOf'以外のリフレクション)をもたらすかどうか知っていますか? –

+0

答えを編集して結果のバイトコードを表示し、コメントの質問に答える自由を取った - これは本当に「安い」操作であるようだ:) –

1

私はあなたが正しく何をしようとして理解していれば、あなたは木のためのコンパニオンオブジェクトを追加し、それにEmptyValueを定義しようとすることができます:

問題はそれだけで特定の case objectで発生したかのように見えます
class Tree(val id: Int) { /******/ } 
object Tree { 
    case object EmptyValue 
} 
+0

問題は、ツリーは実際には3つのタイプ、従って 'ツリー[S、D、A]'にparametrisedされます。内部の型を使うときにのみパターンマッチングを使うことができます。そうしないと、駄目なマッチャーが型の消去について文句を言うからです。それは非常に複雑なデータ構造です。内側の型を移動すると、1日の作業がかかります。私は疑問を編集して、これは奇妙なことに、「ケースオブジェクト」の問題に過ぎないことを示しています。 –

関連する問題