我对Java中的继承和转换有疑问。我有以下两个示例类和一个测试类,我在类之后陈述我的问题:
public class Automobile {
public int var;
public Automobile () {
var = 1;
}
public String toString () {
return "AUTOMOBILE: " + var;
}
}
public class Porsche extends Automobile {
public int var;
public Porsche () {
var = 2;
}
public String toString () {
return "PORSCHE: " + var;
}
}
public class Test {
public static void main (String [] args) {
Porsche p = new Porsche();
Automobile a = new Automobile();
System.out.println ("(Automobile) p = " + (Automobile)p);
System.out.println ("(Automobile) p.var = " + ((Automobile)p).var);
}
}
输出结果为:
(Automobile) p = PORSCHE: 2
(Automobile) p.var = 1
我不明白为什么在第二个声明中我们有1.它不应该是2吗?因为在我在第一个语句中将p转换为汽车后,我仍然得到PORSCHE: 2
作为p
的表示 - 我通过以下方式理解这一点:
尽管如此,我已将p
投放到汽车p
保持其“原始性质” - p
是保时捷一类的对象,但由于保时捷延伸了汽车,我们可以说p是也是一辆汽车。因此,当我们将它明确地转移到汽车时,它继续使用它的方法 - 在
我们的案例是保时捷中定义的方法toString()
。
另一方面,如果我写的是正确的,那么第二个印刷语句应该给出2而不是1.
现在这似乎与我相矛盾,但由于这在Java中起作用,似乎我不明白在转换和继承过程中发生了什么。
答案 0 :(得分:16)
我相信你实际上无法覆盖Java中的变量。子类实际上“隐藏”变量var
。
当您转向Automobile
时,您将获得var
变量的超类版本。但是,toString()
方法仍在查看实例的var
变量版本。
如果您从保时捷子类中删除public int var
,它应该按预期工作。
应该注意的是,使用公共实例变量并不是一种好习惯,您应该始终创建getter / setter以使其具有正确的encapsulation。
答案 1 :(得分:5)
隐含变量var
。
您的Porche.var
是与Automobile.var
不同的变量。
Porsche.toString()
方法使用Porsche.var
,而演员表示编译器使用Automobile
版本。
答案 2 :(得分:2)
对字段的访问不是多态的 - 它仅取决于表达式的编译时类型。
表达式((Automobile)p)具有编译时类型Automobile,因此使用其字段。
答案 3 :(得分:1)
在两个类中声明变量“var”,实际上在内存中创建了两个字段。
“保时捷”的一个实例将在内存中有两个“var”字段,一个是“Porsche”类,另一个是超级“汽车”。当您从已知的“保时捷”实例中引用“var”时,会隐藏超类的“var”字段。如果将此实例强制转换为“Automobile”并引用“var”字段,则引用“Automobile”的var字段。
在字段中没有重写。具有相同名称的新字段掩盖了超类的字段。
要获得预期结果,您根本不应在“保时捷”类中声明“var”字段。
答案 4 :(得分:0)
但是:
如果您有一个返回父类A对象的方法,它可以返回任何对象类型扩展它的类(工厂示例)。现在,如果此方法返回子类B对象,并且如果不将其强制转换为B,则其所有属性都将是父属性。如果将其强制转换为B,则其属性将为A和B属性。
class A {
int a1,a2;
public A(){}
public static A getInstance () {
return new B() ;
}
}
class B {
int b1,b2;
public B() {}
}
class Test{
public static void main (String [] args) {
A theA = A.getInstance() ; //here theA has only a1,a2 as attributes
B theB = (B)theA // here theB has b1,a2 and a1,a2 as attributes
}
}