Конструктор Scala для вопроса о классах дел - PullRequest
2 голосов
/ 14 июля 2011

Я озадачен чем-то в Скале. Кажется, у меня есть объекты с одинаковым адресом, но разным содержимым. Я сталкивался с этой проблемой при использовании Kiama. Но для простоты я свел весь код к следующему:

object CaseTests {
  trait Attributable extends Product {
    var parent: Attributable = null;

    private def setChildConnections = {
        var i : Int = 0        
        for (i <- 0 until productArity) {
            productElement (i) match {
                case c : Attributable => c.parent = this
                case _ => 
            }
        }

    }
    setChildConnections
  }

  abstract class Tree extends Attributable { def id = super.toString }
    case class Pair (left : Tree, right : Tree) extends Tree { println(this+" = "+super.toString + " = ("+left.id+", "+right.id+")"); }
    case class Leaf (value : Int) extends Tree { println(this+" = "+super.toString); }

  def main(args: Array[String]): Unit = {
      val l1 = Leaf(1);
      val l2 = Leaf(1);
      val tree = Pair (Leaf (1), Pair (Leaf (1), Leaf (2)))
      val Pair(left1: Tree, sub: Tree) = tree
      val Pair(left2: Tree, right: Tree) = sub 
      println("left1 = "+left1.id)
      println("left2 = "+left2.id)
      println("left1.parent = "+left1.parent)
      println("left2.parent = "+left2.parent)
  }
}

Когда я запускаю свой тестовый пример, я получаю это как вывод:

Leaf(1) = org.modelica.v4.tests.full.CaseTests$Leaf@fe67d8d2
Leaf(1) = org.modelica.v4.tests.full.CaseTests$Leaf@fe67d8d2
Leaf(1) = org.modelica.v4.tests.full.CaseTests$Leaf@fe67d8d2
Leaf(1) = org.modelica.v4.tests.full.CaseTests$Leaf@fe67d8d2
Leaf(2) = org.modelica.v4.tests.full.CaseTests$Leaf@de2f8005
Pair(Leaf(1),Leaf(2)) = org.modelica.v4.tests.full.CaseTests$Pair@d8e41584 = (org.modelica.v4.tests.full.CaseTests$Leaf@fe67d8d2, org.modelica.v4.tests.full.CaseTests$Leaf@de2f8005)
Pair(Leaf(1),Pair(Leaf(1),Leaf(2))) = org.modelica.v4.tests.full.CaseTests$Pair@6a311526 = (org.modelica.v4.tests.full.CaseTests$Leaf@fe67d8d2, org.modelica.v4.tests.full.CaseTests$Pair@d8e41584)
left1 = org.modelica.v4.tests.full.CaseTests$Leaf@fe67d8d2
left2 = org.modelica.v4.tests.full.CaseTests$Leaf@fe67d8d2
left1.parent = Pair(Leaf(1),Pair(Leaf(1),Leaf(2)))
left2.parent = Pair(Leaf(1),Leaf(2))

Чего я не понимаю (и я подозреваю, что это потому, что я упускаю какой-то тонкий момент об эквивалентности в Scala / Java или, возможно, я просто неверно интерпретирую вывод), так это то, как left1 и left2 имеют одинаковый адрес ( или я неправильно это понимаю) но разные родители?!

Если бы кто-то мог меня поправить, я был бы очень признателен. Спасибо.

P.S. - Я запускаю Scala 2.9, на случай, если это имеет значение.

Ответы [ 2 ]

6 голосов
/ 14 июля 2011

left1 и left2 не являются одинаковыми объектами.Попробуйте println(left1 eq left2), он напечатает false.Метод toString по умолчанию вызывает Integer.toHexString(hashCode), поэтому вы обязательно получите тот же id, если хеш-код двух объектов совпадает.И здесь это происходит, потому что case-классы автоматически получают достойную реализацию hashCode и equals.

0 голосов
/ 20 июля 2011

Просто примечание: System.identityHashCode () - отличный трюк, но учтите, что он также не всегда гарантирует возвращение уникального результата - я видел, как он возвращает одинаковые числа для двух разных живых объектов.

...