Java 具有实例变量的多态性
下面是我写的三个类:Java 具有实例变量的多态性,java,variables,polymorphism,overriding,instance,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() { retu
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类的主方法的输出为:
I am a rectangle!
1
I am a rectangle!
L*W
0
1
我是一个长方形!
1.
我是一个长方形!
L*W
0
1.
为什么s.x返回0而不是1?因为变量的当前实例不是矩形,并且该类也声明了相同的实例变量,或者矩形类中的变量没有像对矩形类中的getX()方法那样重写Shape类中的前一个公共x变量,从而返回1
同样,作为一般规则,超类只有在其子类方法也在该类中声明时才可以访问其子类方法的实现?这是因为编译器将看到“Shape”类中有相同数量的具有相同签名的方法(使用重写的矩形实现),并接受这些方法作为有效的Shape方法吗
提前感谢,子类只继承超类中的变量和方法,而不是相反。所以为了使x等于1,你必须称之为矩形而不是形状。除非你做了其他人演示的铸造,你应该在实际编程中尽可能避免。另外,永远不要使用公共实例变量!如果您希望变量是公共的,至少让它们成为静态或常量。Java中的字段没有多态性。然而,也有继承权。有效的做法是在矩形类中创建两个同名字段。字段的名称实际上是:
public class Rectangle {
public int Shape.x;
public int Rectangle.x;
}
上述内容并不代表有效的Java,它只是说明了字段在类中的作用域
在矩形类的整个范围内,相同名称的超类字段是隐藏的。因此,每当您在类中引用简单名称x
,或作用域名称this.x
,您都会引用在矩形中定义的字段。实际上,您也可以使用作用域名称super.x
访问超类字段
现在,从类外部来看,访问字段的规则略有不同。范围将由引用字段的类的编译时间类型决定。因此,在您的代码中:
Shape s = new Shape();
Rectangle r = new Rectangle();
s = r;
System.out.println(s.x);
输出是0
,因为s
的编译时类型是Shape
(不是矩形
)。执行此操作时,可以观察到此行为的变化:
Shape s = new Shape();
Rectangle r = new Rectangle();
s = r;
System.out.println(((Rectangle)s).x);
普雷斯托!您的输出现在是1
,因为编译器看到您已将字段访问范围限定为矩形
要压缩可见性规则,请执行以下操作:
您可以在中阅读更多关于实例变量隐藏的信息,为什么您的实例变量是公共的?!!永远不要将实例变量公开!!!这是一个测试,看看会发生什么。我很清楚封装,因为我以前做过MVC设计。谢谢,现在我明白了!那么这些方法是否像我在使用s.getArea()时所说的那样使用矩形实现呢?我知道它们看起来很像,但编译时实际发生了什么?Thanks@PragmaticProgrammer-方法的规则不同,一方面,它们实际上可以被覆盖。还记得我说过,对于隐藏变量,解析是在编译时完成的吗?对于重写的方法,解析是在运行时完成的。所以,如果你做了Shape s=new Rectangle();s、 getArea()
调用的方法用于子类矩形
,而不是超类形状
。