Наследование Java, циклическое прохождение через каждый подкласс

#java #class #inheritance

#java #класс #наследование

Вопрос:

Я пытаюсь перебрать несколько объектов разных типов, которые все расширяют один и тот же родительский класс. Например:

 ArrayList<Enchant> enchants = new ArrayList<>();
  

Внутри массива enchants будут объекты классов, которые расширяют Enchant класс.

Например:

 public class JumpBoost extends Enchant{
    public static Item generateItem(){
        return something;
    }
}
  

У каждого объекта в зачаровывающем ArrayList будет метод с именем generateItem() .

Я хотел бы пройти через него, используя:

 for(Enchant enchant : enchants){
    enchant.generateItem()
}
  

Я уже пытался это сделать, но безуспешно из-за того, что класс Enchant не имеет generateItem() метода.

По сути, мне просто нужен способ группировать и перебирать несколько объектов разных типов.

Ответ №1:

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

Вы также можете попробовать создать интерфейс, с generateItem() помощью которого все подклассы реализуют и сохраняют тип интерфейса в ArrayList .

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

Ответ №2:

Вы можете использовать полиморфизм для решения этой проблемы.
Сначала определите базовый класс / абстрактный класс / интерфейс с помощью метода generateItem(), производите указанные классы и переопределяйте / реализуйте метод generateItem() .
Вот реализация с интерфейсом:

 interface Base{
    void generateItem();
}
class Derived1 implements Base{
    @Override
    public void generateItem() {
        System.out.println("generateItem() from Derived1");
    }
}
class Derived2 implements Base{
    @Override
    public void generateItem() {
        System.out.println("generateItem() from Derived2");
    }
}
class Main {
    public static void main(String[] args) {
        List<Base> list = new ArrayList<>();
        list.add(new Derived1());
        list.add(new Derived2());
        list.forEach(Base::generateItem);
    }
}
  

Вывод:

 generateItem() from Derived1
generateItem() from Derived2
  

Подробнее о полиморфизме вы можете прочитать здесь .

Комментарии:

1. Разве второй вывод не должен быть из Derived2?

Ответ №3:

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

 public class Enchant {
    public abstract Item generateItem();
}
  

Метод не должен быть static методом, как у вас есть в вашем коде. Это должен быть метод экземпляра, поскольку вы вызываете его в экземплярах Enchant .

Ответ №4:

Создайте enchant как интерфейс или абстрактный класс и расширьте его в производных классах