Запуск абстрактного конструктора, затем приведение к подклассам - PullRequest
2 голосов
/ 20 января 2012

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

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

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

1 Ответ

4 голосов
/ 20 января 2012

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

  • Абстрактные классы не могут быть созданы;конструктор абстрактного класса может быть вызван только в конструкторе подкласса.
  • Даже если родительский класс не был абстрактным, приведение (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, хотя это будет медленнее.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...