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いわば「パスの依存関係をエスケープ」しないようにアイデンティティを修正するエレガントな方法は何ですか。シリアル化が行われているときに壊れる次のようなコードがあります。

def insert(point: Point, leaf: Leaf): Unit = {
  val qidx = hyperCube.indexOf(point)
  child(qidx) match {
    case EmptyValue => ...
    ...
  }
}

つまり、コンパイラは私の一致が完全であると言いますが、シリアライゼーションを使用するとランタイムMatchErrorが発生します(バイト配列に書き込み/読み取りを行うカスタムコードがあります)。たとえば、ツリー内からTree$EmptyValue$@4636a を取得して呼び出していますがTree$EmptyValue$@3601、それらは一致しません。

編集

内部型を外に移動する必要がないようにしたいので、さらにテストを実施しました。型パラメーターが必要になるため、すべてのパターン マッチング コードが壊れてしまうからです。問題はその特定のものでのみ発生するように見えますcase object:

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
4

2 に答える 2

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
...
于 2012-03-27T16:49:30.767 に答える
1

あなたが正しくやろうとしていることを理解できたら、Tree のコンパニオン オブジェクトを追加し、その中で EmptyValue を定義してみてください。

class Tree( val id: Int ) { /******/ }
object Tree {
  case object EmptyValue
}
于 2012-03-27T16:23:47.847 に答える