在容器中存储已从同一抽象类扩展的不同对象

时间:2012-08-08 15:42:56

标签: java inheritance casting polymorphism abstract-class

是否可以将从同一抽象对象扩展的不同对象存储在单个容器中,并且能够访问这些对象的所有自定义字段。让我举一个例子:   假设我有两辆车:福特和本田。由于所有汽车都有重量和颜色,我可以制作以下抽象类:

public abstract class Car{

  private double weight; 
  private String color;

  public Car(){
    this.weight=0;
    this.color="";
  }
  ...getters and 
  ...setters
}

现在假设我的福特班有一个额外的字段' radio ',看起来像这样:

public Ford extends Car(){
private String radio;

public Ford(){
super();
this.radio = "generic";
}
}

同样,Honda类有一个自定义字段“相机

public Honda extends Car(){
  private String camera;

  public Honda(){
    super();
    this.camera= "analog";
  }
}

是否可以将这些类的实例保存在单个容器中,如下所示。请注意下面的代码有效,但这不是我想要的。见下面的评论:

Ford ford = new Ford();
Honda honda = new Honda();
ArrayList<Car> myCars = new ArrayList<Car>();
myCars.add(ford);
myCars.add(honda);

这是我的问题: 当我myCars.get(0)时,我得到了一个类Car的对象(显然),我永远无法获得自定义字段 radio 。当然我可以做((Ford) myCars.get(0))这样的事情,并且能够看到无线电字段,但是有可能创建一个更好的容器,可以显示所有字段而无需向下转换等等喜欢: myContainer.get(0) - 会返回 Ford 类,我可以访问权重,颜色和广播 myContainer.get(1) - 将返回本田课程,我可以访问重量,颜色和相机

我的预感告诉我解决方案已经接近并且有可能,但我在Java方面的专业知识尚未实现。也许我对某种泛型或哈希映射做了什么?

谢谢你们!!

3 个答案:

答案 0 :(得分:2)

有几种选择,其中没有一种完全符合您的理想。

  • 您可以在Car类中添加特定属性的所有getter,并返回Null或在不适用的情况下抛出异常。
  • 您可以应用Visitor pattern
  • 您可以创建一个包含列表的CarContainer类,并具有返回特定类型的所有元素的方法,例如: List<Ford> getAllTheFords()。通过这种方式,您可以隐藏容器类中的丑陋演员表。

我根据个人喜好列出了替代方案: - )

答案 1 :(得分:2)

你可以做的是使用泛型。

您的存储库可以实现这些方法:

public static <T extends Car> T getFromRepository(Class<T> type, Object key) 
public static <T extends Car> boolean addToRepository(Class<T> type, Object key, T value)

然后你可以用类似的东西来打电话(假设你已经拥有了福特的钥匙):

Ford ford = Repository.getFromRepository(Ford.class, fordKey)

当然,您可以实现方法来获取给定类型的所有对象,等等......

PS:一个简单的替代方案,如果你可以在子类上使用相同的方法是模板方法模式: http://en.wikipedia.org/wiki/Template_method_pattern

答案 2 :(得分:1)

myCars.get(0)会返回一个福特对象。除了这只是在运行时才知道。问题是,要拨打car.radio,您需要知道它是福特,如果不是,您就不能调用该方法。所以在任何情况下你都需要检查类型和演员。

一种解决方案是在您的抽象类中添加List<Accessory>字段。

您现在可以编写如下内容:

Car car = cars.get(0);
if (car.hasAccessories()) {
    car.getAccessory(0).operate();
}

不确定这是否是您的用例所需。