2016-04-05 8 views
4

は、次のインターフェイスクラスを持っている:ダウンキャスティングを避ける必要がある場合は、どうすればよいですか?

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ハッシュマップにで格納します。私はそれを取得する場合

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

が、私はIGameObjectでしょう、どのように私はそれを適切にキャストしない、私がアクセスできるように、 ChargeGunの方法?

+0

ダウンキャスティングなしでこれを行う方法は他にありません。特定の型のマップまたは既にキャストされたオブジェクトのマップのみを取得するメソッドを持つInventoryMapクラスを作成するなど、何かと変わってしまう可能性があります。しかし、フードの下ではそれはまだダウンキャスティングです。 –

+0

ありがとう、ちょっと好奇心から、どのように私はそれをきれいにするだろうか? –

+0

消耗品などの他のアイテムについては、どのようなクラスメソッドも異なるので、在庫を分割してください。 –

答えて

5

visitor patternを使用すると、キャストできなくなります。アイデアは単純です:IGameObjectのインベントリがあり、これはv.visit(this)を直接呼び出すメソッドaccept(GameObjectVisitor v)を持ちます。 GameObjectVisitorでは、訪問(Chargegun g)、訪問(Sword s)などの実装のための訪問メソッドを実装するだけで済みます。

別の方法で説明すると、ブーメランの原則のようです:GameObjectVisitorはitem.accept(this)を呼び出し、Item実装はaccept(GameObjectVisitor g)を単純なg.visit(this)で呼び出します。

このようにすることで、Visitorは各実装に対して複数の訪問メソッドを持ち、instanceofをキャスト/使用することなく特定の処理を行うことができます。

+0

このパターンでは、ReloadメソッドであるChargeGunでしか使用できないメソッドにはまだアクセスできますか? –

+0

はい、IGameObjectVisitorで宣言した訪問(ChargeGun chargeGun)では、パラメータをChargeGunとして宣言しているため、すべての特定のメソッドを使用できます。 –

関連する問題