I've tried the code below (the equal method is written after Programming in Scala book)
class Person() {
class Room(r: Int, c: Int) {
val row = r
val col = c
override def hashCode: Int =
41 * (
41 + row.hashCode
) + col.hashCode
override def equals(other: Any) =
other match {
case that: Room =>
(that canEqual this) &&
this.row == that.row &&
this.col == that.col
case _ => false
}
def canEqual(other: Any) =
other.isInstanceOf[Room]
}
val room = new Room(2,1)
}
val p1 = new Person()
val p2 = new Person()
println(p1.room == p2.room)
>>> false
After some analysing I found that Scala redefines the class Room
for each instance of Person
and that's the reason the two rooms aren't equal.
One possibility to resolve the problem is to put the class outside of the class Person
, but this isn't always what's easiest. (For example if the class has to access some parameters of Person
.)
What alternatives are there to write the equal method?
A pattern match includes a sequence of alternatives, each starting with the keyword case. Each alternative includes a pattern and one or more expressions, which will be evaluated if the pattern matches. An arrow symbol => separates the pattern from the expressions.
Notes. Scala's pattern matching statement is most useful for matching on algebraic types expressed via case classes. Scala also allows the definition of patterns independently of case classes, using unapply methods in extractor objects.
Case classes are Scala's way to allow pattern matching on objects without requiring a large amount of boilerplate. In the common case, all you need to do is add a single case keyword to each class that you want to be pattern matchable.
Pattern matching is a way of checking the given sequence of tokens for the presence of the specific pattern. It is the most widely used feature in Scala. It is a technique for checking a value against a pattern. It is similar to the switch statement of Java and C.
The problem is that your two rooms are instances of a path-dependent type: their types are p1.Room
and p2.Room
:
scala> :type p1.room
p1.Room
One way to make this work is to refer to Room
using type selection, i.e. as Person#Room
.
class Person() {
class Room(r: Int, c: Int) {
val row = r
val col = c
override def hashCode: Int = // omitted for brevity
override def equals(other: Any) =
other match {
case that: Person#Room =>
(that canEqual this) &&
this.row == that.row &&
this.col == that.col
case _ => false
}
def canEqual(other: Any) =
other.isInstanceOf[Person#Room]
}
val room: Room = new Room(2,1)
}
val p1 = new Person()
val p2 = new Person()
scala> p1.room == p2.room
res1: Boolean = true
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With