Я продовжую це питання , але я перемикаю свою увагу з коду на принцип.
З мого розуміння принципу заміщення Ліскова (LSP), які б методи не були в моєму базовому класі, вони повинні бути реалізовані в моєму підкласі, і відповідно до цієї сторінки, якщо ви перекриєте метод в базовому класі, і він нічого не робить або кидає виняток, ви порушуєте принцип.
Тепер мою проблему можна підсумувати так: у мене є конспект Weapon
class
і два класи, Sword
і Reloadable
. Якщо в ньому Reloadable
міститься конкретний method
, що називається Reload()
, мені доведеться перейти вниз, щоб отримати доступ до цього method
, і в ідеалі ви хочете цього уникнути.
Тоді я думав скористатися Strategy Pattern
. Таким чином, кожна зброя усвідомлювала лише ті дії, які вона здатна виконувати, тому, наприклад, Reloadable
зброя може, очевидно, перезавантажуватися, але Sword
не може, і навіть не знає про це Reload class/method
. Як я вже зазначив у своїй публікації про переповнення стека, мені не доведеться робити приниження, і я можу підтримувати List<Weapon>
колекцію.
На іншому форумі перша відповідь запропонувала дозволити Sword
собі знати Reload
, просто нічого не робіть. Ця сама відповідь була надана на сторінці переповнення стека, яку я пов’язував вище.
Я не повністю розумію, чому. Навіщо порушувати принцип і дозволяти Мечу усвідомлювати це Reload
, і залишати його порожнім? Як я вже говорив у своєму дописі Stack Overflow, SP, в значній мірі вирішив мої проблеми.
Чому це не життєздатне рішення?
public final Weapon{
private final String name;
private final int damage;
private final List<AttackStrategy> validactions;
private final List<Actions> standardActions;
private Weapon(String name, int damage, List<AttackStrategy> standardActions, List<Actions> attacks)
{
this.name = name;
this.damage = damage;
standardActions = new ArrayList<Actions>(standardActions);
validAttacks = new ArrayList<AttackStrategy>(validActions);
}
public void standardAction(String action){} // -- Can call reload or aim here.
public int attack(String action){} // - Call any actions that are attacks.
public static Weapon Sword(String name, damage, List<AttackStrategy> standardActions, List<Actions> attacks){
return new Weapon(name, damage,standardActions, attacks) ;
}
}
Напад інтерфейсу та реалізація:
public interface AttackStrategy{
void attack(Enemy enemy);
}
public class Shoot implements AttackStrategy {
public void attack(Enemy enemy){
//code to shoot
}
}
public class Strike implements AttackStrategy {
public void attack(Enemy enemy){
//code to strike
}
}
reload()
порожнім або standardActions
не містить дії перезавантаження, це просто інший механізм. Принципової різниці немає. Можна зробити і те, і інше. => Ваше рішення є життєздатним (який був ваш питання).; Меч не повинен знати про перезавантаження, якщо Weapon містить пусту реалізацію за замовчуванням.
class Weapon { bool supportsReload(); void reload(); }
. Клієнти перевірять, чи підтримується перед перезавантаженням.reload
визначається договірно, щоб кинути iff!supportsReload()
. Це дотримується класів, керованих LSP iff, дотримується протоколу, який я лише окреслив.