Java中的继承和转换

时间:2009-01-30 10:49:41

标签: java inheritance casting

我对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中起作用,似乎我不明白在转换和继承过程中发生了什么。

5 个答案:

答案 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 
  }


}