セッションでシリアル化および逆シリアル化されるクラスがあり、内部クラスでパターン マッチングを実行する必要があります。内部クラスの識別に問題があります:
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$@4636
a を取得して呼び出していますが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