访问子类中的重写值

时间:2015-07-01 13:30:29

标签: java class override

假设我有一个抽象的父类:

public class Foo extends Bar {
    public int count = 1;
}

现在我有几个具体的子类。假设一个是:

count

现在我想迭代扩展抽象类的子集合。当我问他们List<Bar> l = new ArrayList<Bar>(); l.add(new Foo()); for (Bar b : l) { System.out.println(b.count.toString()); // This always gives 0. } 的值时,我发现我得到的是父母的初始值,而不是孩子初始化的值:

76

我显然使用了错误的类模型。什么是正确的方法,以便我可以获得子类初始化的值?

3 个答案:

答案 0 :(得分:4)

您的迭代引用类型Bar,作为List的参数化类型。

因此,它会count Bar的{​​{1}}属性,隐藏在Foo的{​​{1}}之内。

这就是你得到count的原因。

如果您想要动态变量解析,请实现并覆盖返回0的方法。

如果您还使用更合适的访问修饰符设置count,那么这将有助于您的封装设计。

最后的注释

引用您的评论:

  

我更喜欢坚持使用字段,因为我有很多这些字段

为您的字段实现getter和setter应该是微不足道的。

事实上,一旦宣布了字段,就可以通过在任何可敬的IDE中遵循快速向导来获得自动草稿或完全实现的方法。

作为一般规则,如果您的字段是可变的,您可以考虑不使用模板getter。

作为另一个一般规则,如果您的字段在设置之前需要验证,您可以考虑不使用按原样实现的模板设置器。

我建议您仔细研究encapsulation的概念。

答案 1 :(得分:1)

Access to fields在编译时解析。没有像字段覆盖的概念,只有字段阴影Foo中的 count 字段会影响继承的{{1} } {} {}}中的字段。

为避免阴影和混淆,您应该将继承类中的字段重命名为count

尽管如此,如果您要打印Bar中定义的fooCount字段,您可以这样做:

count

当然,正如其他答案中所建议的那样,您应该重新考虑这种设计是否良好(并且第一个可能不太好的信号是使用Foo运算符),并使用多态来实现相同的效果目标以更易读和可维护的方式。

答案 2 :(得分:0)

作为Mena答案的补充,我想指出在子类中隐藏超类属性通常是一团糟,显然不是一个好的面向对象设计。

如果您希望FooBar个对象具有不同的值,为什么不使用构造函数以不同方式初始化count字段?这是达到您要求的最直接方式。

public class Bar {
  public int count ;

  public Bar() {
    count = 0;
  }
}

public class Foo extends Bar {
  public Foo() {
    count = 1
  }
}

使用此代码,您可以轻松利用多态来循环List<Bar>并收集count,而无需强制转换,或者不为Bar的每个子类定义getter