开发者

Scala constructor for case classes question

I'm puzzled by something in Scala. I seem to have objects that have the same address, but different contents. I came across this issue while using Kiama. But to keep things simple, I boiled all the code down to this:

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+")"); }
    cas开发者_运维知识库e 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)
  }
}

When I run my test case, I get this as output:

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))

What I don't understand (and I suspect this is because I am missing some subtle point about equivalence in Scala/Java or perhaps I'm simply misinterpreting the output) is how left1 and left2 appear to have the same address (or am I misinterpreting that), but different parents?!

If somebody could set me straight, I would really appreciate it. Thanks.

P.S. - I'm running Scala 2.9, in case it matters.


left1 and left2 are not the same objects. Try println(left1 eq left2), it will print false. The default toString method calls Integer.toHexString(hashCode), so you're bound to get the same id if the hash code of two object matches. And here it does, because case classes automatically get a decent hashCode and equals implementation.


Just a note: System.identityHashCode() is an excellent trick, but note that it's also not always guaranteed to return a unique result -- I've seen it return identical numbers for two different live objects.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜