运行抽象构造函数,然后转换为子类

时间:2012-01-20 01:27:33

标签: java inheritance casting constructor

是否可以在一个方法中调用抽象构造函数,然后将其传递给其他一些方法,这些方法会将新对象转换为特定的子类?也就是说,

public AbstractClass createNewAbstractClass() {
    //do lots of checks that are the same for each sub class,
    //including geting and checking each variable,
    //and an exception thrown by the constructor.
    AbstractClass abstractClassObject = new AbstractClass(var1, ...);
    return abstractClassObject;
}

public SubClassOne createSubClassOneObject() {
    SubClassOne subClassOneObject = (SubClassOne)createNewAbstractClass(var1,..);
    return subClassOneObject;
}

public SubClassTwo createSubClassTwoObject() { ...

解决这个问题的一种方法是获取并检查一个方法中的所有变量,然后将它们返回到数组中,以便方法createSubClassNObject()可以在正确的构造函数中使用它们,但这似乎相当凌乱,这意味着每个创建方法都必须以相同的方式检查相同的异常,并对它做同样的事情,这听起来就像你应该尝试外包到另一个方法的情况!

我对实际观点感兴趣 - 我希望我的代码整洁可读 - 但从理论的角度来看 - 这实际上是可能的吗?所以,即使答案是否定的,你能解释一下原因吗?

1 个答案:

答案 0 :(得分:4)

这有几个问题:

  • 抽象类无法实例化;只能在子类的构造函数中调用抽象类的构造函数。
  • 即使父类不是抽象的,(SubClassOne)强制转换也会失败,因为我们确实有一个AbstractClass类型的实例,而不是类型为SubClassOne的实例AbstractClass

很遗憾,返回SubClassOne的方法需要调用SubClassOne构造函数,该构造函数可能采用与AbstractClass相同的参数,只需委托super调用

我认为在每个工厂方法中复制一些异常处理代码并不容易。构造函数与多态性不匹配。你可以有一个返回AbstractClass的中心构造函数,但它需要一个参数(一个枚举,一个Class,无论如何)来告诉它要调用哪个子类构造函数。

abstract class Cow {
  Cow() throws Exception {
    ... // possible exceptions
  }
}

class FatCow extends Cow {
  FatCow() throws Exception {
    super();
    ...
  }
}

class GreenCow extends Cow {
  GreenCow() throws Exception {
    super();
    ...
  }
}

enum CowType {
  FAT_COW, GREEN_COW;
}

class CowMachine {
  static Cow makeCow(CowType type) {
    try {
      switch (type) {
        case FAT_COW:
          return new FatCow();
        case GREEN_COW:
          return new GreenCow();
        default:
          throw new IllegalArgumentException();
      }
    } catch (Exception e) {
      ...
      return null;
    }
  }

  static Cow makeFatCow() {
    return (FatCow) makeCow(CowType.FAT_COW);
  }

  static Cow makeGreenCow() {
    return (GreenCow) makeCow(CowType.GREEN_COW);
  }
}

如果你不想要一个大的swtich语句,你可以接受一个Class对象并调用newInstance,虽然这会慢一些。