问题
I have:
sealed trait BEValue
case class BEByteString(val value: Array[Byte]) extends BEValue {
def equals(that: BEByteString): Boolean = this.value.deep == that.value.deep
def ==(that: BEByteString) = this equals that
}
case class BEList(val value: List[BEValue]) extends BEValue
BEByteString("spam".getBytes) == BEByteString("spam".getBytes) //true
val l1 = BEList(BEByteString("spam".getBytes):: Nil)
val l2 = BEList(BEByteString("spam".getBytes):: Nil)
l1 == l2 // false. Why ?
回答1:
You should not create your own ==
method. In scala ==
method is implemented using equals
.
You should use override
keyword to override equals
method.
case class BEByteString(val value: Array[Byte]) extends BEValue {
override def equals(that: BEByteString): Boolean = this.value.deep == that.value.deep
}
// <console>:11: error: method equals overrides nothing
// override def equals(that: BEByteString): Boolean = this.value.deep == that.value.deep
// ^
You have created a new equals
method. And your new ==
method is implemented using your new equals
method. But case class equals is implemented using Any#equals
method for parameters.
Any#equals
method signature is def equals(that: Any): Boolean
case class BEByteString(val value: Array[Byte]) extends BEValue {
override def equals(that: Any): Boolean = that match {
case BEByteString(thatValue) => thatValue.deep == this.value.deep
case _ => false
}
}
l1 == l2
// Boolean = true
Note that you could use IndexedSeq[Byte]
instead of Array[Byte]
. In this case you could use a default equals
implementation. It also makes your BEByteString
class immutable: with Array[Byte]
one can change a content of value
.
来源:https://stackoverflow.com/questions/21370705/equality-and-case-classes