4

私は Java を学び始めたばかりなので、答えがある程度明白である場合はご容赦ください。私はいくつかの調査を行いましたが、役に立ちませんでした。

私が理解していることから、属性はオーバーライドされず、フィールドのみが非表示になっています。スーパークラスとサブクラスのどちらの属性が使用されているかを判断するために、Java は参照の型をチェックします。

次に、ここでの出力を理解していません:

public class Super {
    String str = "I'm super!\n";

    public String toString() {
        return str;
    }
}

public class Sub extends Super {
    String str = "I'm sub.\n";
}

public class TestFH {
    public static void main(String[] args) {
        Sub s1 = new Sub();

        System.out.printf(s1.toString());
    }
}

それは私に与えます:

I'm super!

メソッドのオーバーライドを介して簡単に目的を達成できることを理解しています。ボンネットの下で何が起こっているのか興味があります。

前もって感謝します。

4

4 に答える 4

4

を呼び出すと、クラスでのみ定義されたメソッドs1.toString()が検出されるため、そのメソッドをスーパークラスメソッドとして使用してサブクラスで使用できます。スーパークラスメソッドは、メソッドからの戻り値として独自のクラス変数(スーパークラスで初期化された値を持つ)を使用しているため、動作、つまり として出力されます。toString()SupertoString()strI'm super!

出力を取得したい場合I'm sub.\nは、スーパークラスと同じ変数を再利用し、新しい文字列値を割り当てる必要がありますI'm sub.\n。最良のオプションは、コンストラクターを次のように使用することです。

  public class Super {
     String str = "I'm super!\n";

     public Super(String stringValue){
         this.str = stringValue;
     }

     public String toString() {
        return str;
     }
  }

  public class Sub extends Super {
     public Sub(){
       super("I'm sub.\n");
     }
  }

  public class TestFH {
    public static void main(String[] args) {
       Sub s1 = new Sub();
       System.out.printf(s1.toString());
    }
  }
于 2012-12-21T05:00:10.767 に答える
2

str子クラスに隠れています (シャドウイング) 。子クラスでオーバーライドしていないためtoString()、呼び出しは親クラスで行われ、親のstr.

これを行った場合:

public class Sub extends Super {
    public Sub() {
        this.str = "I'm sub.\n";
    }
}

それはあなたが期待しているものを出力します。

于 2012-12-21T05:06:55.097 に答える
1

この呼び出しはスーパー クラスを使用しています。

Sub s1 = new Sub();
System.out.printf(s1.toString());

その理由は、Sub がオーバーライド strしていないためです。たまたま同じ名前を持つ別の変数を宣言しているだけです。つまり、sub は単に変数を隠しているだけですSuper(データ メンバーは多態的ではありません)。

意味が異なる場合は、別の名前を付けることができます。またはSub、getter メソッドを使用して親の属性にアクセス (または変更) することもできます。

于 2012-12-21T04:59:32.900 に答える
1

文字列リテラル"I'm sub.\n"を共有スーパークラス フィールドに割り当てているのではなく、サブクラスに対してローカルなフィールドを作成し、代わりにそれに割り当てています。

例えば、

public class EncapsulationDemo {

    public static void main(String[] args){
        MySuperObject obj = new MySubObject();

        System.out.println(obj); // prints I'm sub.
    }

    private static class MySuperObject{
        String str = "I'm super."; // protected, can be accessed directly 
                                   // by subclasses

        @Override
        public String toString(){
            return str;
        }
    }

    private static class MySubObject extends MySuperObject{
        MySubObject(){
            super();
            str = "I'm sub."; // assign to superclass field
        }
    }
}

詳細については、クラスのメンバーへのアクセスの制御を参照してください。

于 2012-12-21T05:02:46.723 に答える