与实例变量的多态性

时间:2013-03-20 01:05:04

标签: java variables polymorphism override instance

以下是我写的三个课程:

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

I am a rectangle!

1

I am a rectangle!

L*W

0

1

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

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

提前致谢,

2 个答案:

答案 0 :(得分:13)

Java中的字段没有多态性。但是,继承。你已经有效地完成了在Rectangle类中创建两个具有相同名称的字段。该字段的名称有效:

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

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

在Rectangle类的整个范围内,同名的超类字段是 hidden 。因此,只要您在类中引用简单名称x或范围名称this.x,就会引用Rectangle中定义的字段。您实际上也可以使用范围名称super.x来访问超类字段。

现在,从类的外部来看,访问该字段的规则略有不同。范围将由引用该字段的类的 编译 时间类型确定。所以在你的代码中:

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

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

输出为0,因为s的编译时类型为Shape(不是Rectangle)。执行此操作时,您可以观察到此行为的变化:

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

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

的Presto!您的输出现在是1,因为编译器发现您已将对Rectangle的字段访问限定为范围。

浓缩可见度规则:

您可以在JLS, Section 8.3.3.2

中详细了解隐藏的实例变量

答案 1 :(得分:0)

子类只继承超类中的变量和方法,而不是相反。因此,为了使x等于1,你必须调用矩形而不是形状。除非你做其他人用铸造演示的东西,你应该尽可能地避免在实际编程中。另外,你永远不应该使用公共实例变量!如果你想让变量公开,至少让它们变为静态或不变。