2016-04-05 3 views
4

haben folgende Interface-Klasse:Wenn Downcasting vermieden werden sollte, was soll ich tun?

public interface IGameObject { 

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

ich die folgende abstrakte Klasse, die die obige Schnittstelle implementiert.

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; 
} 

Ich bin auf ein paar Beiträge gestoßen, die vorschlagen Downcasting sollte vermieden werden. Ich verstehe, warum, ABER, meine Frage ist, was ich tun muss, wenn ich auf eine Methode zugreifen muss, die für eine Unterklasse spezifisch ist. Zum Beispiel:

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() 
{ 

} 

speichere ich in in einem Interventory hashmap etwa so:

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

Wenn ich es wieder, werde ich ein IGameObject bekommen, wie kann ich es richtig gegossen, so dass ich zugreifen kann die Methode in ChargeGun?

+0

Ich sehe keine andere Möglichkeit, dies ohne Downcasting zu tun. Sie können es als etwas anderes tarnen, z. B. zum Erstellen einer InventoryMap-Klasse, die Methoden zum Abrufen nur von Maps bestimmter Typen oder von bereits heruntergekommenen Objekten enthält, um den Code möglicherweise etwas zu bereinigen. Aber unter der Haube ist es immer noch niedergeschlagen. –

+0

Danke, nur aus Neugier, wie würde ich es aufräumen? –

+0

Sie sollten wahrscheinlich Ihr Inventar aufteilen, denn was ist mit anderen Artikeln wie Verbrauchsmaterialien usw. Sie haben alle unterschiedliche Klassenmethoden –

Antwort

5

Sie können die visitor pattern verwenden, die Sie vom Casting befreit. Die Idee ist einfach: Sie haben ein Inventar von IGameObject, das eine Methode akzeptiert (GameObjectVisitor v), die v.visit (this) direkt aufruft. In Ihrem GameObjectVisitor müssen Sie nur Visit-Methoden für jede Implementierung implementieren: Zum Beispiel visit (Charge gun), visit (Sword s), etc ...

Um es auf eine andere Weise zu erklären, ist es wie das Prinzip eines Bumerangs : Der GameObjectVisitor ruft item.accept (this) auf und das Item implementiert accept (GameObjectVisitor g) mit einem einfachen g.visit (this).

Dadurch hat der Besucher mehrere Besuchsmethoden für jede Implementierung und kann bestimmte Dinge tun, ohne instanceof casten/verwenden zu müssen.

+0

Kann ich mit diesem Muster immer noch auf die Methode zugreifen, die nur für ChargeGun, die Reload-Methode, verfügbar ist? –

+0

Ja, weil Sie in Ihrem IGameObjectVisitor in dem Besuch (ChargeGun chargeGun) den Parameter als ChargeGun deklariert haben und somit alle spezifischen Methoden verfügbar sind. –