Получение данных из подкласса без создания экземпляров - PullRequest
2 голосов
/ 03 марта 2009

У меня есть абстрактный суперкласс и различные подклассы. Каждый подкласс содержит значение, которое я хотел бы использовать статически, но невозможно создать абстрактный статический метод. Я хочу получить значение от них динамически, не создавая экземпляры. Что мне делать?

Другой вопрос: как бы я перебрал подклассы? Это вообще возможно?

Одна попытка состояла в том, чтобы сопоставить имена классов (Subclass.class) со значением и попытаться использовать для них newInstance, чтобы я мог использовать метод для получения значения, но это не работает.

Где я ошибаюсь в моем подходе?

Ответы [ 7 ]

1 голос
/ 03 марта 2009

Может быть, вы ищете перечисления?

public enum Planet
{
  MERCURY (2.4397e6),
  VENUS   (6.0518e6),
  EARTH   (6.37814e6);

  private final double radius;

  Planet(double radius)
  {
    this.radius = radius;
  }

  public double radius()
  {
    return radius;
  }
}

Вам не нужно создавать enum экземпляры самостоятельно. Перечисления могут иметь значения, например radius() в примере. Вы можете добавить к ним поведение, чтобы они могли вести себя как обычные классы, определив для них абстрактные методы, например

public enum Planet
{
  ...
  abstract double weightOnSurface(double weight);
  ...
}

Вы можете перебирать перечисления следующим образом:

for (Planet p : Planet.values())
{
  System.out.println(p.radius());
}

Так что, похоже, они соответствуют всем вашим критериям.

1 голос
/ 03 марта 2009

Вы можете ссылаться на статические члены / методы с помощью отражения, но не существует автоматического способа найти все подклассы класса.

Рассмотрите возможность предоставления подклассов / экземпляров фабрик / классов метаданных с помощью какого-либо другого механизма, такого как ServiceLoader сервисов или некоторой другой инфраструктуры плагинов.

1 голос
/ 03 марта 2009

Почему бы не пойти другим путем? Поместить данные в статически доступное место и получить от них подклассы?

Конечно, выполнимость этого зависит от характера данных, но когда вы сталкиваетесь с таким барьером, это часто помогает отступить и пересмотреть ваши предположения.

- MarkusQ

0 голосов
/ 04 марта 2009

Создание второго класса для каждого из ваших подклассов, который представляет тип этого подкласса, может работать.

Например, создайте фабричный класс для каждого подкласса (класс, который отвечает за создание экземпляров этого подкласса). Должен быть только один экземпляр каждого фабричного класса.

Каждый фабричный класс может быть ответственным за знание специфичных для подкласса данных, которые вы описываете. Затем вам просто нужно перебрать фиксированный набор фабричных классов.

0 голосов
/ 04 марта 2009

Отображение подклассов ... вы можете сделать это с помощью отражения (но это не будет весело).

newInstance () (скорее всего) не будет работать, если:

  • класс публичный
  • конструктор публичный
  • конструктор не принимает аргументов

Последнее является обязательным, два других зависят от того, из какого пакета вы делаете вещи (я думаю, это было некоторое время, так как я заботился). Лучше использовать класс Constructor.

Можете ли вы привести краткий пример того, что вы думаете делать? Исходя из этого, я (и другие) мог бы дать вам лучшие ответы. Если вам нужно сделать вещь подкласса отображения, я могу найти некоторый код, который это делает ...

0 голосов
/ 03 марта 2009

Вам нужно будет сканировать пакеты и кластеры, чтобы найти те, которые расширяют ваш суперкласс - к сожалению, этого нельзя сделать с помощью API Reflection, но это нужно сделать через URL-адреса (классы файловой системы, файлы JAR и т. Д.). В этом случае, вероятно, лучше использовать аннотации, и многие продукты с открытым исходным кодом используют этот метод (Hibernate и т. Д.).

Тогда у вас может быть статический метод в каждом (либо последовательное именование, либо аннотированный), который вы сможете использовать как method.invoke(MyObject.class, arguments)

Другой вариант - поместить карту реестра в абстрактный класс - если вам нужно назначить его, абстрактный конструктор принимает статическое значение (или просто сохраняет подкласс, если требуются вычисления). Если вы управляете всеми подклассами, просто убедитесь, что в каждом из них есть статический блок, чтобы добавить его в реестр.

0 голосов
/ 03 марта 2009

Если у вас есть фиксированный набор подклассов, вы можете поместить данные в суперкласс. Если ваши подклассы могут быть добавлены, то нет способа перечислить их все. Вы можете получить подклассы, чтобы сообщить суперклассу об их существовании из статического инициализатора (или использовать агент!).

Как правило, суперклассы не должны знать о своих подклассах. Однако вы можете подумать (или лучше реорганизовать) свой суперкласс в супертип и какой-то другой класс, отвечающий за ваши подклассы.

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