抽象类与抽象字段和子类没有强制转换

时间:2012-04-24 16:48:01

标签: java generics design-patterns

我创建了一个抽象基类。它包含一个应该由任何子类扩展的对象:

public abstract class AbstractParent {
    protected AbstractObject subMePlz;
    // ... some fields that all subclasses need
    public AbstractParent() {
        this.subMePlz = createThisInYourExtendedClass();

    }

    public abstract AbstractObject createThisInYourExtendedClass();
} 

abstractObject:

public abstract class AbstractObject {
   // ... some fields/methods that all subclasses need 
}

我想要的是能够在不扩展的情况下使用扩展类中的扩展字段:

public class ExtendParent extends AbstractParent {
     // .. some unique fields
     public ExtendParent(){
       super();
     }


   public ConcreteObject createThisInYourExtendedClass(){
        return new ConcreteObject();
   }

   // what I want to do - no cast
   public void doSomethingWithSubMePlzWithoutCastingIt() {
        System.out.println(this.subMePlz);  
   }

   // what I end up doing - gotta cast
   public void doSomethingWithSubMePlzWithoutCastingIt() {
        System.out.println((ConcreteObject)this.subMePlz);  
   }
}

需要一个比较器来改变我应该如何实现它吗? - 我正在考虑一个通用比较器,用于可以由其子类使用的AbstractObjects列表。

4 个答案:

答案 0 :(得分:4)

听起来你需要让它变得通用:

public abstract class AbstractParent<T extends AbstractObject> {
    protected T subMePlz;
    // ... some fields that all subclasses need
    public AbstractParent() {
        this.subMePlz = createThisInYourExtendedClass();

    }

    public abstract T createThisInYourExtendedClass();
} 

public class ExtendParent extends AbstractParent<ConcreteObject> {
    ...
}

请注意,在构造函数中调用非私有方法通常是一个坏主意 - 子类尚未完全初始化,这可能使得很难推断出你可以真正实现多少依靠。

答案 1 :(得分:3)

您有两种选择:

  1. 放弃项目以声明超类中的字段。相反,向您的超类添加内部抽象“getter”方法 - 基本上,AbstractParent应该有一个方法abstract AbstractObject getSubMePlz()
  2. 使用泛型设置子类中subMePlz的类型:定义AbstractParent<T>以使其T字段具有subMePlz
  3. 就个人而言,我经常发现选项1非常令人愉快地可扩展 - 例如,您可以使用另一个子类来缩小getSubMePlz()返回类型而不会声明它,这可能是有利的。

答案 2 :(得分:0)

为什么不使用它 -

     super.subMePlz

而不是 -

    (ConcreteObject)this.subMePlz

这样,你就不需要演员了。

答案 3 :(得分:0)

您可以在子类中保存对象的副本,但使用正确的类。

public class ExtendParent extends AbstractParent {
  ConcreteObject concreteObject;

  public AbstractObject createThisInYourExtendedClass(){
    ConcreteObject concreteObject = new ConcreteObject();
    return concreteObject;
  }
  public void doSomethingWithSubMePlzWithoutCastingIt() {
    System.out.println(concreteObject);  
  }

  ...