Как сопоставить шаблон вложенного класса в Scala? - PullRequest
9 голосов
/ 02 декабря 2011

Я попробовал приведенный ниже код (метод равенства написан после Программирование в 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

После некоторого анализа я обнаружил, что Scala переопределяет класс Roomдля каждого экземпляра Person и по этой причине две комнаты не равны.

Одна из возможностей решения проблемы - поместить класс вне класса Person, но это не всегдачто проще всего(Например, если класс должен получить доступ к некоторым параметрам Person.)

Какие существуют альтернативы, чтобы написать метод равных?

1 Ответ

15 голосов
/ 02 декабря 2011

Проблема в том, что ваши две комнаты являются экземплярами типа, зависящего от пути: их типы p1.Room и p2.Room:

scala> :type p1.room
p1.Room

Один из способов выполнить эту работу - обратиться к Room с использованием выбора типа, т.е. как 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
...