7

重複の可能性:
シャドーイングの概念

クラスのフィールドがアップキャスト中に Java でどのように処理されるかについて混乱しています。例えば:

class SuperClass
{
    String myString = "String in SuperClass";

    public void myMethod()
    {
        System.out.println("Method in SuperClass");
    }
}

class SubClass extends SuperClass
{
    String myString = "String in SubClass";

    public void myMethod()
    {
        System.out.println("Method in SubClass");
    }
}

class Question
{
    public static void main(String[] args)
    {
        SuperClass test = new SubClass();
            // object test is an instance of SubClass
            // but I am telling the compiler to treat it as SuperClass

        test.myMethod();
        System.out.println(test.myString);

    }
}

出力:

Method in SubClass
String in SuperClass //Why is "String in SubClass" not used?

オブジェクトを作成すると、testそれはSubClassクラスのインスタンスです。ただし、コンパイラに として扱うように指示していSuperClassます。SubClassメソッドの動作についてはすべて明らかです。特定のメソッドが に対して定義されている場合にのみ、 のメソッドを使用できますSuperClass

ただし、のにSuperClassアクセスしようとすると、なぜ a のフィールドが使用されるのかわかりません。のインスタンスが使用されると予想されるので、なぜこれが起こらないのですか? 私は何が欠けていますか?myStringtesttestSubClassmyStringSubClass

SubClass演算子を使用してmyString にアクセスできることはわかっていますthis。たとえばprintMyString、SuperClass でメソッドを定義し、それを次のように上書きできます。

public void printMyString()
{
    System.out.println(this.myString);
}

では、SubClass私の質問は主に のフィールドが でどのようにSuperClass使用されるかについてtestです。多分私は明らかな何かを見逃していますか?

答えを検索しようとしましたが、見つけた最も近いトピックはUpcasting in Java と 2 つの個別のオブジェクト プロパティでしたが、役に立ちましたが、私の質問には答えませんでした。

前もって感謝します

4

2 に答える 2

7

属性はメソッドのようにオーバーロードできません。

test.myMethod(); 

ここでのメソッド呼び出しは、実際のオブジェクトのタイプによって異なります。ここでオブジェクトは型SubClassなので、のメソッドSubClassが呼び出されます。

test.myString

属性へのアクセス中は、参照変数のタイプに依存します。ここで参照変数 ietestはタイプでSuperClassあるため、属性 fromSuperClassがアクセスされます。

あなたが探しているのは、クラス変数の非表示/シャドウイングです。

于 2013-01-01T06:24:52.817 に答える
4

Java のフィールドは隠されているだけで、実際にはオーバーライドされていません (これは、これを試行しているときにコンパイル時にエラーが発生するという意味ではなく、実際にはオーバーライドされていません)。

オーバーライドとは、宣言された型ではなく、オブジェクトの実行時の型に基づいてメンバーを呼び出す必要があることを意味します。

ただし、Java でのフィールドのバインドは常に静的であるため、オブジェクト参照の宣言された型のみに基づいています。

あなたが与えた例では、クラスで「myString」という名前のクラス変数を宣言することにより、同じ名前「myString」でSubClassスーパークラスから継承したクラス変数を非表示にします。SuperClass

Java 言語仕様:

クラスが特定の名前のフィールドを宣言する場合、そのフィールドの宣言は、スーパークラスおよびクラスのスーパーインターフェースで同じ名前を持つフィールドのすべてのアクセス可能な宣言を隠すと言われます。

非表示フィールドは、静的な場合は修飾名を使用するか、キーワード super またはスーパークラス型へのキャストを含むフィールド アクセス式を使用してアクセスできます。

于 2013-01-01T06:25:53.910 に答える