Во-первых, давайте рассмотрим проблему поиска нужного вам экземпляра:
scala> trait AbstractOp
defined trait AbstractOp
scala> case class Pop() extends AbstractOp {
| override def equals(other: Any) = other match {
| case that: Pop => this eq that
| case _ => false
| }
| }
defined class Pop
scala> case class PushInt(val i: Int) extends AbstractOp {
| override def equals(other: Any) = other match {
| case that: PushInt => this eq that
| case _ => false
| }
| }
defined class PushInt
scala> val l = List(PushInt(1), PushInt(1), Pop(), Pop())
l: List[Product with AbstractOp] = List(PushInt(1), PushInt(1), Pop(), Pop())
scala> val op = l(1)
op: Product with AbstractOp = PushInt(1)
scala> println( l.indexOf( op ) )
1
Это, конечно, означает PushInt(1) != PushInt(1)
, если только это не тот же самый экземпляр PushInt(1)
. Это не нарушает equals
/ hashCode
контракт, потому что a.equals(b) => a.hashCode == b.hashCode
, но a.hashCode == b.hashCode
ничего не значит. Но если вы используете для поиска этого экземпляра, попробуйте вместо этого:
scala> case class Pop() extends AbstractOp
defined class Pop
scala> case class PushInt(val i: Int) extends AbstractOp
defined class PushInt
scala> val l = List(PushInt(1), PushInt(1), Pop(), Pop())
l: List[Product with AbstractOp] = List(PushInt(1), PushInt(1), Pop(), Pop())
scala> val op = l(1)
op: Product with AbstractOp = PushInt(1)
scala> println( l.findIndexOf( op eq _ ) )
1
В любом случае, если вы повторно вставите этот экземпляр в список, у вас будут проблемы. Вы должны убедиться, что каждый экземпляр, который вы вставляете, уникален. Вы даже можете написать свою собственную коллекцию, либо сгенерировать исключение, если вставлен повторяющийся экземпляр, либо сделать копию любого экземпляра, переданного ему (достаточно просто с классами дел и методом copy
в Scala 2.8).