Pra*_*mer 5 java variables polymorphism overriding 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());
}
}
Run Code Online (Sandbox Code Playgroud)
Tester类的main方法的输出是:
I am a rectangle! 1 I am a rectangle! L*W 0 1
为什么sx返回0而不是1?因为变量的当前实例不是Rectangle,并且该类也声明了相同的实例变量,或者Rectangle类中的变量不会覆盖Shape类中的前一个公共x变量,就像它对getX()一样矩形类中的方法因此返回1?
另外作为一般规则,超类只有在该类中声明它们时才能访问其子类方法的实现?这是因为编译器会看到具有相同签名的相同数量的方法在"Shape"类中(具有重写的Rectangle实现)并接受那些作为有效的Shape方法吗?
提前致谢,
Per*_*ion 13
Java中的字段没有多态性.但是,继承.你已经有效地完成了在Rectangle类中创建两个具有相同名称的字段.该字段的名称有效:
public class Rectangle {
public int Shape.x;
public int Rectangle.x;
}
Run Code Online (Sandbox Code Playgroud)
以上并不代表有效的Java,它只是说明了字段在类中的作用域
在Rectangle类的整个范围内,隐藏了同名的超类字段.因此,只要您在类中引用简单名称x或作用域名称this.x,就会引用其中定义的字段Rectangle.您实际上也可以使用作用域名称访问超类字段super.x.
现在,从类的外部,访问字段的规则略有不同.范围将由引用该字段的类的编译时类型确定.所以在你的代码中:
Shape s = new Shape();
Rectangle r = new Rectangle();
s = r;
System.out.println(s.x);
Run Code Online (Sandbox Code Playgroud)
输出是0因为编译时类型s是Shape(不是Rectangle).执行此操作时,您可以观察到此行为的更改:
Shape s = new Shape();
Rectangle r = new Rectangle();
s = r;
System.out.println(((Rectangle)s).x);
Run Code Online (Sandbox Code Playgroud)
普雷斯托!您的输出现在是1,因为编译器发现您已将字段访问范围限定为Rectangle.
浓缩可见性规则:
您可以在JLS的8.3.3.2节中阅读有关实例变量隐藏的更多信息