Создание объектов, чей подкласс будет зависеть от пользовательского ввода - PullRequest
1 голос
/ 06 июня 2019

Пожалуйста, извините за глупые вопросы, я довольно новичок в Java и ООП и пытаюсь следовать шаблонам проектирования (избегая ifs, переключателей и т. Д.), Но мне трудно это делать.

Итак, я создаю поставщика оружия для собственного «игрового» проекта. У этого продавца есть список объектов. Все эти объекты являются различными экземплярами Суперкласса оружия (например, Меч, Копье, Топор и т. Д.).

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

У меня сейчас две проблемы:

1) Как создать экземпляр объекта, подкласс которого будет зависеть от пользовательского ввода? 2) Как я могу вызвать правильного конструктора, передавая те же параметры оружия, которое было куплено, новому объекту, который будет создан? Я пытаюсь сделать это максимально полиморфным способом, избегая операторов if и switch.

До сих пор я пытался создать интерфейс (iWeapon). Затем на основе этого интерфейса я создал Фабрику, которая получает тип оружия (String) и возвращает новый экземпляр оружия с соответствующим подклассом.

Это позволило мне создать «общее» оружие, используя тип данных интерфейса. Однако я не знаю, является ли это оптимальным способом достижения этого. Кроме того, я не знаю, как полиморфно инициализировать атрибуты нового экземпляра теми же значениями недавно купленного оружия.

Я попытался создать метод 'getAttributesFromOtherWeapon' на всех моих подклассах оружия, который получает объект с теми же типами и просто копирует эти значения. Проблема, с которой я сталкиваюсь сейчас, состоит в том, что объект типа iWeapon, который я создаю, не имеет этого метода, и если я включаю его в интерфейс, я получаю сообщение об ошибке в своих подклассах, в котором говорится, что «класс должен быть объявлен как абстрактный или реализовать абстрактный метод». «

Мой код поставщика делает что-то вроде этого:

Weapon weaponToBuy = (Weapon) weaponList.get(weaponChosenIndex);
iWeapon newWeapon = weaponFactory.getWeapon(weaponToBuy.type);
newWeapon.getAttributesFromOtherWeapon(weaponToBuy);

Однако, поскольку newWeapon является iWeapon, мне нужно было объявить getAttributesFromOtherWeapon в его интерфейсе, который выглядит следующим образом:

public interface iWeapon {


    void getAttributesFromOtherWeapon(iWeapon iWeapon);


}

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

Я думаю, что есть, вероятно, нестандартное решение для этого, которого я не вижу, потому что я нуб на Java. Любая помощь будет оценена по достоинству

1 Ответ

0 голосов
/ 06 июня 2019

Существуют различные решения для этого.

1.Используйте генерики

interface Weapon<T extends Weapon> {
    public Weapon getAttributesFromOther(T t);
}

class Axe implements Weapon<Axe> {
    @Override
    public Weapon getAttributesFromOther(Axe other) {
        // TODO get those attributes
        return this;
    }
}

... и т. Д.

Плюсы

Sword#getAtributesFromOther займет толькоSword, если класс определен как implements Weapon<Sword>.

Минусы

Если по ошибке вы объявляете что-то вроде class Dagger implements Weapon<Pitchfork>, тогда getAttributes займет Pitchfork.

Незначительно, на мой взгляд, поскольку все это время компиляции, но стоит задуматься.

Также ваши ссылки на оружие должны измениться на Weapon<?> для неизвестных типов оружия во время выполнения.

2.Объявите класс WeaponProperties, расширяющий некоторые параметризованные Map, и пару получатель / установщик в интерфейсе Weapon

Pros

Это будет работать детально свсе оружие, вы просто должны проверить, есть ли имущество.

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

Минусы

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

3.Там, вероятно, это что-то еще лучше - отредактирую, если у меня есть идея

Примечания

  • Обязательно следуйте Соглашения о Java-коде , например, нет ничего плохого в венгерской нотации, но каждый тип всегда должен быть CamelCase (в отличие от имен переменных, которые camelBack).Это касается вашего iWeapon интерфейса, который вы легко можете просто изменить на Weapon - см. Пример выше.
  • Запоздалая мысль: я понял, что getAttributes... методы в моем примере возвращают Weapon, но это не такотношение к этому делу - вы можете спокойно вернуть void вместо
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...