我对Scala中的某些东西感到困惑。我似乎有对象具有相同的地址,但内容不同。我在使用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,以防万一。
答案 0 :(得分:6)
left1
和left2
不是同一个对象。试试println(left1 eq left2)
,它会打印错误。默认的toString
方法调用Integer.toHexString(hashCode)
,因此如果两个对象的哈希码匹配,则必须获得相同的id
。它确实如此,因为案例类会自动获得一个不错的hashCode
和equals
实现。
答案 1 :(得分:0)
只需注意:System.identityHashCode()是一个很好的技巧,但请注意,它并不总能保证返回一个独特的结果 - 我已经看到它为两个不同的活动对象返回相同的数字。