2012-01-20 4 views
2

Можно ли вызвать абстрактный конструктор одним методом, а затем передать его каким-либо другим методам, который каждый из них перенесет новый объект в определенные подклассы? То есть,Запуск абстрактного конструктора, затем отбрасывание на подклассы

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() мог использовать их в правильном конструктору, но это кажется довольно беспорядочным, и это будет означать, что каждый метод создания должен будет одинаково проверять одно и то же исключение и делать то же самое с этим, что звучит точно так же, как в ситуации, когда вы должны попытаться передать другой метод другому аутсорсингу!

Меня интересует практическая точка зрения - я хочу, чтобы мой код был аккуратным и читаемым, но также с теоретической точки зрения, действительно ли это возможно? Поэтому, даже если ответ отрицательный, вы можете объяснить, почему?

ответ

4

Есть несколько проблем с этим:

  • абстрактные классы не могут быть созданы; конструктор абстрактного класса может быть вызван только в конструкторе подкласса.
  • Даже если родительский класс не был абстрактным, приведение (SubClassOne) завершится неудачно, потому что у нас действительно будет экземпляр типа AbstractClass, а не экземпляр типа SubClassOne, который вводится как AbstractClass.

Так, к сожалению, метод, который возвращает SubClassOne нужно будет вызывать SubClassOne конструктор, который может принимать такие же параметры, как AbstractClass и просто делегировать с super вызова.

Я не думаю, что есть простой способ дублирования кода обработки исключений в каждом вашем заводском методе; конструкторы плохо играют с полиморфизмом. У вас может быть центральный конструктор, который возвращает AbstractClass, но для этого потребуется параметр (enum, 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, хотя это будет медленнее.

+0

ОК, спасибо. Это немного очистило абстрактные классы в моей голове - я думаю, я понимаю, почему невозможно делать то, что я просил. – DenverCoder8