问题
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