【发布时间】:2013-11-13 13:43:59
【问题描述】:
我之前问了一个问题:here,虽然我接受了答案,但我离真正理解还很远,所以我挖得更深了,我正在写一个进一步的问题。
在 scala 中覆盖 val 的行为让我感到惊讶。例如,给定以下代码:
class A {
val name = "AAAAA"
}
class B extends A {
override val name = "BBBBB"
}
如果我说:
object Atest extends App {
val b = new B
println(b.name)
val a = b.asInstanceOf[A]
println(a.name)
}
我期待
BBBBB
AAAAA
但我明白了
BBBBB
BBBBB
我只是想查看我认为 A 应该存储在某处的 AAAAA 值。所以我尝试:
class A {
val name = "AAAAA"
def showSuper {
println(name)
}
}
和:
val b = new B
val a = b.asInstanceOf[A]
b.showSuper
a.showSuper
但我仍然得到:
BBBBB
BBBBB
所以我试着看看 scala 从我的课程中实际生成了什么:
scalac -Xprint:all A.scala
给我
class A extends Object {
private[this] val name: String = _;
<stable> <accessor> def name(): String = A.this.name;
def <init>(): p3.A = {
A.super.<init>();
A.this.name = "AAAAA";
()
}
};
class B extends p3.A {
private[this] val name: String = _;
override <stable> <accessor> def name(): String = B.this.name;
def <init>(): p3.B = {
B.super.<init>();
B.this.name = "BBBBB";
()
}
}
对 B.super 的调用发生在 B.this.name 甚至被设置之前,并且 A 清楚地将其名称设置为 AAAAA。
发生了什么事?为什么,当我覆盖这样的 val 时,我看不到 A 的值(或者它是否被设置为 B 的值?)发生这种情况的机制是什么?我如何才能看到这种机制 - 是否有一段 scala 源代码告诉我为什么会发生这种情况?
非常感谢
编辑: 补充一点,如果我使用 javap 查看字节码,它清楚地表明 A 和 B 都有自己的 name 变量副本:
$ javap -private A
Compiled from "A.scala"
public class p3.A extends java.lang.Object{
private final java.lang.String name;
public java.lang.String name();
public p3.A();
}
$ javap -private B
Compiled from "A.scala"
public class p3.B extends p3.A{
private final java.lang.String name;
public java.lang.String name();
public p3.B();
}
因此,A 和 B 不必共享同一个变量 - 他们每个人都有可能使用自己的副本。
【问题讨论】:
-
This answer 可能会提供信息
-
谢谢,但我认为这与选角无关。在上面的示例中,即使是 b.showSuper,我也希望显示 AAAAA,因为它显式调用其超类的方法,其中引用了 A 的字段(或者至少在我看来)
标签: scala