以前に質問しました:ここで答えを受け入れましたが、実際に理解するにはまだほど遠いので、もう少し掘り下げて、さらに質問を書いています。
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 が同じ変数を共有する必要はありません。それぞれが独自のコピーを使用する可能性があります。