7

私が書いた3つのクラスは次のとおりです。

public class Shape {

    public int x = 0;

    public void getArea() {
        System.out.println("I don't know my area!");
    }

    public String toString() {
        return "I am a shape!";
    }

    public int getX() {
        return x;
    }
}

public class Rectangle extends Shape {

    public int x = 1;

    public int getX() {
        return x;
    }

    public void getArea() {
        System.out.println("L*W");
    }

    public String toString() {
        return "I am a rectangle!";
    }
}

public class Tester {

    public static void main(String[] args) {
        Shape s = new Shape();
        Rectangle r = new Rectangle();

        System.out.println(r);
        System.out.println(r.x + "\n");

        s = r;
        System.out.println(s);
        s.getArea();
        System.out.println(s.x);
        System.out.println(s.getX());
    }
}

Tester クラスのメイン メソッドからの出力は次のとおりです。

私は長方形です!

1

私は長方形です!

長さ×幅

0

1

sx が 1 ではなく 0 を返すのはなぜですか? 変数の現在のインスタンスが Rectangle ではなく、そのクラスにも同じインスタンス変数が宣言されているか、または Rectangle クラスの変数が、getX() に対する場合のように、Shape クラスの以前のパブリック x 変数をオーバーライドしていないか。矩形クラスのメソッドしたがって、1 を返しますか?

また、原則として、スーパークラスは、そのクラスでも宣言されている場合にのみ、そのサブクラスのメソッドの実装にアクセスできますか? これは、同じシグネチャを持つ同量のメソッドが (オーバーライドされた Rectangle 実装を持つ) 「Shape」クラスにあり、それらを有効な Shape メソッドとして受け入れることをコンパイラが確認するためですか?

前もって感謝します、

4

2 に答える 2

15

Java にはフィールドのポリモーフィズムはありません。ただし、継承があります。効果的に行ったことは、Rectangle クラスに同じ名前の 2 つのフィールドを作成することです。フィールドの名前は、実質的に次のとおりです。

public class Rectangle {
    public int Shape.x;
    public int Rectangle.x;
}

上記は有効な Java を表すものではありません。クラス内でフィールドがどのようにスコープされているかを示しているだけです。

Rectangle クラスのスコープ全体で、同じ名前のスーパークラス フィールドはhiddenです。したがって、クラス内で単純な名前xまたはスコープ名を参照するときはいつでも、で定義されているフィールドを参照しています。実際には、スコープ名を使用して、スーパークラス フィールドにもアクセスできます。this.xRectanglesuper.x

さて、クラスの外側から見ると、どのフィールドがアクセスされるかのルールが少し異なります。スコープは、フィールドが参照されているクラスのコンパイル時の型によって決定されます。だからあなたのコードで:

Shape s = new Shape();
Rectangle r = new Rectangle();

s = r;
System.out.println(s.x);

出力は0、のコンパイル時の型sShape(not Rectangle) であるためです。これを行うと、この動作の変化を観察できます。

Shape s = new Shape();
Rectangle r = new Rectangle();

s = r;
System.out.println(((Rectangle)s).x);

プレスト!1フィールド アクセスのスコープを に設定したことがコンパイラによって認識されるため、出力はになりますRectangle

可視性のルールを要約するには:

JLSでのインスタンス変数の非表示の詳細については、セクション 8.3.3.2 を参照してください。

于 2013-03-20T01:29:57.477 に答える
0

サブクラスはスーパークラスの変数とメソッドのみを継承し、その逆は継承しません。したがって、xを1に等しくするには、形状ではなく長方形を呼び出す必要があります。他の人がキャストで示したものを実行しない限り、実際のプログラミングではできるだけ避ける必要があります。さらに、パブリックインスタンス変数を使用しないでください。変数をパブリックにしたい場合は、少なくともそれらを静的または定数にします。

于 2013-03-20T01:20:42.157 に答える