0

以前に質問しました:ここで答えを受け入れましたが、実際に理解するにはまだほど遠いので、もう少し掘り下げて、さらに質問を書いています。

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 が同じ変数を共有する必要はありません。それぞれが独自のコピーを使用する可能性があります。

4

2 に答える 2

2

これは Scala 固有のものではありません。OOPの質問です。2 番目のクラスは、メソッドをオーバーライドして非表示にします。 メソッドのオーバーライドと非表示

于 2013-11-13T13:57:53.403 に答える