У меня есть класс, который сериализуется и десериализуется в сеансе, и мне нужно выполнить сопоставление образцов во внутренних классах. У меня возникли проблемы с идентичностью внутренних классов:Удовлетворение идентификатора объекта/соответствия шаблона при сериализации
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
при использовании сериализации (я имею пользовательский код, записывает/читает из массивов байтов). Например, я звоню из дерева, имеющего [email protected]
, и извлекаю [email protected]
, и они не совпадают.
EDIT
я провел дополнительные испытания, потому что я действительно хотел бы избежать необходимости перемещать внутренние типы вне, так как они должны иметь параметры типа и, таким образом, разорвать весь шаблон, соответствующий код. Это выглядит так, как если проблема возникает только с этой конкретной 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
Это замечательно Юджин. Знаете ли вы, что это определение 'equals' представляет собой какое-то время исполнения (отражение, отличное от' isInstanceOf')? –
Я взял на себя смелость, чтобы отредактировать ваш ответ, показывая полученный байт-код и, таким образом, отвечая на вопрос моего комментария - кажется, это действительно «дешевая» операция :) –