7

这是我写的三个类:

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 类的 main 方法的输出是:

我是长方形!

1

我是长方形!

长*宽

0

1

为什么 sx 返回 0 而不是 1?因为变量的当前实例不是 Rectangle 并且该类也声明了相同的实例变量,或者 Rectangle 类中的变量没有覆盖 Shape 类中以前的公共 x 变量,就像它对 getX() 所做的那样矩形类中的方法因此返回 1?

同样作为一般规则,超类只有在该类中也声明了其子类方法时才能访问其实现?这是因为编译器将看到具有相同签名的相同数量的方法在“Shape”类中(具有重写的 Rectangle 实现)并接受这些作为有效的 Shape 方法?

提前致谢,

4

2 回答 2

15

Java 中的字段没有多态性。但是,有继承。您实际上所做的是在 Rectangle 类中创建两个具有相同名称的字段。该字段的名称实际上是:

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

以上并不代表有效的 Java,它只是说明字段在您的类中的作用域

在 Rectangle 类的整个范围内,同名的超类字段是隐藏的。因此,每当您在类中引用简单名称x或作用域名称this.x时,您指的是在 中定义的字段Rectangle。您实际上也可以使用作用域名称访问超类字段super.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,您必须调用矩形而不是 shape。除非您按照其他人演示的铸造方式进行操作,否则在实际编程中应尽可能避免。另外,您永远不应该使用公共实例变量!如果您希望变量公开,至少使它们成为静态或常量。

于 2013-03-20T01:20:42.157 回答