2016-04-05 1 views
4

имеют следующий интерфейс класса:Если вам следует избегать Downcasting, что я должен делать?

public interface IGameObject { 

    String gameObjectID(); 
    String gameObjectName(); 
    void isActionValid(String action); 
    void viewActions(); 
} 

У меня есть следующий абстрактный класс, который реализует интерфейс выше.

package gameprobjectpackage; 

public abstract class Weapon implements IGameObject { 
//Left out getters/setters to keep it simple 
private String gameOjectID; 
private String gameObjectName; 
private int damage; 

public Weapon(String gameOjectID, String gameObjectName,int damage) { 
    super(); 
    this.gameOjectID = gameOjectID; 
    this.gameObjectName = gameObjectName; 
    this.damage = damage; 
} 

Я столкнулся с несколькими сообщениями, которые предполагают, что следует избегать опускания. Я понимаю, почему, НО, мой вопрос - что мне делать, если мне нужно получить доступ к методу, который относится к подклассу. Например:

public class ChargeGun extends Weapon { 


private String [] chargeGunActions; 

public ChargeGun(String gameOjectID, String gameObjectName, int damage) { 
    super(gameOjectID, gameObjectName, damage); 

     chargeGunActions = new String [3]; 
     chargeGunActions[0] = "Charge and Fire"; 
     chargeGunActions[1] = "Release"; 
     chargeGunActions[2] = "Drop Gun"; 
} 

//This method is only meant for gun, and this type of gun is the only one in my game. 
//This method, I don't belive should be in the abstract method weapon, because NOT every weapon is a gun. 

public void reloadGun() 
{ 

} 

хранить в в interventory HashMap так:

Map<String,IGameObject> inventory = new HashMap<String,IGameObject>(); 

Когда я получить его, я получаю IGameObject, как я правильно бросить его, так что я могу получить доступ метод в ChargeGun?

+0

Я не вижу другого способа сделать это без понижения. Вы можете замаскировать его как что-то еще, например, создать класс InventoryMap, который имеет методы для извлечения только карт определенных типов или объектов, которые уже опустились, возможно, немного очистив ваш код. Но под капотом он все еще удручает. –

+0

Спасибо, просто из любопытства, как бы я его очистил? –

+0

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

ответ

5

Вы можете использовать visitor pattern, который освобождает вас от литья. Идея проста: у вас есть инвентарь IGameObject, который будет принимать метод (GameObjectVisitor v), который напрямую вызывает v.visit (это). В вашем GameObjectVisitor вам просто нужно реализовать методы посещения для каждой реализации: например, посещение (Chargegun g), посещение (Sword s) и т. Д.

Чтобы объяснить это по-другому, это похоже на принцип бумеранга : GameObjectVisitor вызывает item.accept (this), а реализация объекта принимает (GameObjectVisitor g) с простым g.visit (это).

При этом посетитель имеет несколько методов посещения для каждой реализации и может выполнять определенные операции без необходимости использовать/использовать instanceof.

+0

С помощью этого шаблона я могу получить доступ к методу, доступному только для ChargeGun, метода перезагрузки? –

+0

Да, потому что во время посещения (ChargeGun chargeGun), которое вы заявляете в своем IGameObjectVisitor, вы объявили параметр как ChargeGun, и, следовательно, все специальные методы доступны. –

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