Ich habe eine Klasse, die in einer Sitzung serialisiert und deserialisiert wird, und ich muss Mustererkennung für innere Klassen durchführen. Ich habe Probleme mit der Identität der inneren Klassen:Fixing-Fall Objekt Identität/Mustererkennung unter Serialisierung
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'
Was für eine elegante Art und Weise ist die Identität für EmptyValue
nicht ‚zu entkommen Pfadabhängigkeit‘ zu beheben, so zu sprechen. Ich habe Code wie die folgenden, die bricht, wenn die Serialisierung stattfindet:
def insert(point: Point, leaf: Leaf): Unit = {
val qidx = hyperCube.indexOf(point)
child(qidx) match {
case EmptyValue => ...
...
}
}
Das heißt, obwohl der Compiler mein Spiel sagt erschöpfende ist, erhalte ich eine Laufzeit MatchError
wenn Serialisierung mit (I benutzerdefinierten Code habe, dass schreibt in/liest aus Byte-Arrays). Zum Beispiel rufe ich von innerhalb des Baumes, der [email protected]
hat und einen Tree$EmptyValu[email protected]
abruft und sie nicht zusammenpassen.
EDIT
ich weitere Tests durchgeführt habe, weil ich wirklich die inneren Typen zu vermeiden, möchte darauf bewegen, wie sie benötigen, um Typ-Parameter und damit brechen alle passenden Codemuster. Es sieht aus, als ob das Problem nur mit diesen speziellen case object
auftritt:
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
Das ist toll Eugene. Weißt du, ob diese Definition von "equals" eine Art von Laufzeit-Penalität darstellt (eine andere Reflektion als 'isInstanceOf')? –
Ich habe mir die Freiheit genommen, Ihre Antwort zu bearbeiten, den resultierenden Byte-Code zu zeigen und somit meine Kommentarfrage zu beantworten - es scheint, dass dies eine wirklich 'billige' Operation ist :) –