2015-11-05 10 views
2

Я работаю над моим проектом java, который является основной ролевой игрой, и у меня есть вопрос OOD (я думаю, это довольно просто, но это мой первый проект java). Я начал работать над оружием, я создал абстрактный класс Weapon с абстрактным методом с именем attack. Оружие имеет два подкласса - MeleeWeapon и RangedWeapon, и оба имеют метод атаки, и все в порядке.Java - абстрактный класс и интерфейс

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

+4

Используйте Throwable Interface. – Luminous

+4

Одно из возможных решений: забыть об абстрактном оружии, создать интерфейс 'MeleeWeapon' (с помощью метода' meleeAttack') и интерфейс 'RangedWeapon' (с помощью метода' rangedAttack'). Теперь класс может реализовать оба интерфейса. – Turing85

+0

@ Turing85, я думал, что интерфейс может помочь здесь, но как я могу различать меч, который можно использовать в качестве оружия ближнего боя и копье, которое является оружием ближнего и дальнего боя? – Niminim

ответ

3

Одним из вариантов является использование композиции, а не наследования.

Каждое оружие может предлагать набор атак. Например, Weapon.getAttacks() возвращает набор поддерживаемых атак. В подклассе Spear.getAttacks() возвращает экземпляры Thrust, Throw и BashBashBash.

Это позволяет использовать ту же атаку с несколькими видами оружия. И булава, и копье могут предложить атаку Bash - только с разным уроном от HP. Вы могли бы Тянуть с копьем или 10-футовым полюсом. Вы можете бросить книгу заклинаний. (И эти вещи больнее, чем вы могли бы подумать.) В общем, вы можете определить результаты любого действия с любым объектом.

+0

Я думал, вы имели в виду в первом сообщении, чтобы использовать только класс оружия, поэтому у каждого оружия будет список доступных атак, таких как бросок и тяга (которые будут методами класса Weapon). – Niminim

+0

Теперь я понимаю, что вы предлагаете создавать классы Thrust and Throw, не так ли? можете ли вы дать короткий пример реализации того, как обращаться с классами Thrust и Throw? – Niminim

+0

Правильно, оружие - это объекты, у которых есть атаки, такие как Thrust and Throw, в дополнение к другим атрибутам. Подкласс класса Weapon, такой как Spear, может инициализировать атаки оружия в конструкторе, передавая соответствующие диапазоны повреждений. Метод 'attack()', который вы цитируете, может быть методом в классе * attack *, а не классом оружия.Для полиморфизма вам понадобится суперкласс «AbstractAttack», который предоставляет абстрактный метод «attack()»). –

0

Мне нравится идея интерфейса и композиции, которые предлагают очень хорошо документированные решения. Но у меня есть третья идея: просто добавьте throw() в MeleeWeapon. Услышьте меня, если вы используете интерфейс, это затруднит случайное создание оружия. Если вы используете композицию, вам нужно начать все заново и создать броски и предметы ближнего боя внутри вашего оружия. Иногда самый простой ответ - путь, тем более, что теперь вы можете ссылаться на свой ближний или дальний объект своим родительским классом и без проблем вызвать метод броска.

+0

Да, это тоже звучит неплохо, и, наверное, самый легкий :). но не будет ли он продублировать код? Я имею в виду, что у RangedWeapon будет атака, а бросок в MeleeWeapon будет идентичен методу атаки в классе RangedWeapon. Любое изменение метода атаки RangedWeapon потребовало бы, чтобы я изменил бросок в MeleeWeapon. – Niminim

+1

Я предположил, что бросок ближнего боя будет отличаться от атаки дальнего боя (потеряйте оружие для расчета поворота или повреждения). Если они являются тем же самым методом, напишите метод ранжированной атаки в родительском классе. Оружие ближнего боя перезапишет это своей рукопашной атакой и может иметь метод броска, который вызывает super.attack(), чтобы получить версию дальнего боя. – Mackie

+0

Я еще не думал об этом. Возможно, кинжал кинжал был бы идентичен выстрелу с луком, но иначе, чем бросать копье. – Niminim

0

Интерфейсы шва, как лучший подход:

Концепция

Может быть сделать свой Weapon класс немного более абстрактно: (. Атака, падение, т.д.) только основные методы, необходимые. Возможно, даже сделать его не абстрактным, чтобы он работал из коробки.

Теперь для специальной функциональности создайте некоторые интерфейсы, которые позволяют такие вещи, как бросок, стрелять, взрываться и т. Д. Таким образом, добавление новых функций в оружие будет намного проще и меньше времени.

Теперь, когда вызывается функция атаки, она может совершать совершенно разные виды атак, основанные на интерфейсах класса оружия.

Дизайн

Базовый класс:

//the general weapon class 
public class Weapon{ 

    //you don't want your base class instantiatable 
    protected Weapon(){} 

    public void attack(){ 
     //take enemy health ect. 
    } 

    public void drop(){ 
     //drop weapon 
    } 
} 

Что вы можете сделать с интерфейсами, делают обратный метод верно, если противник может ударить, или из метода вызова функции атаки если противник может быть поражен.

интерфейс Melee:

public interface Melee { 
    boolean onMelee();//called if the player tries to perform a melee attack 
} 

Стрелковое интерфейс:

public interface Ranged { 
    boolean onRanged();//called if the player tries to perform a ranged attack 
} 

лук класс оружие:

public class WeaponBow extends Weapon implements Ranged{ 

    @Override 
    public boolean onRanged(){ 
     //play animation, check if target is vulnerable, ect. 
     //return true if the enemy can be hit false otherwise 
    } 
} 

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

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

Смежные вопросы