2012-01-20 10 views
1

ここにいます私の状況の代わりに静的フィールドを使用していますジェネリック<T extends A>クラスはTの1つの

public abstract class Actions { 

    public static Actions STAND; 
    public static Actions ATTACK; 
    public static Actions COLONIZE; 
    public static Actions DEFEND; 
    public static Actions TURN_CW; 
    public static Actions TURN_CCW; 
    public static Actions DIE; 

    public abstract long[] getFramesDurations(); 
    public abstract int[] getBaseTiles(); 
} 

public class SimpleActions extends Actions{ 

    public static Actions STAND = new SimpleActions(new long[]{120,120,120,120,120,120,120}, new int[]{0,1,2,3,4,5,6}); 
    public static Actions ATTACK = new SimpleActions(new long[]{120,120,120,120,120,120,120,120,120}, new int[]{7,8,9,10,11,12,13,14,15}); 
    public static Actions COLONIZE = new SimpleActions(new long[]{120,120,120,120,120,120,120}, new int[]{7,8,9,10,11,12,13,14,15}); 
    public static Actions DEFEND = new SimpleActions(new long[]{1}, new int[]{1}); 
    public static Actions TURN_CW = new SimpleActions(new long[]{1}, new int[]{1}); 
    public static Actions TURN_CCW = new SimpleActions(new long[]{1}, new int[]{1}); 
    public static Actions DIE = new SimpleActions(new long[]{1}, new int[]{1}); 

    private final long[] mActionFramesDurations; 
    private final int[] mActionBaseTiles; 

    SimpleActions(long[] pActionFramesDurations, int[] pActionBaseTiles) { 
     mActionFramesDurations = pActionFramesDurations; 
     mActionBaseTiles = pActionBaseTiles; 
    } 

    public long[] getFramesDurations() 
    { 
     return mActionFramesDurations; 
    } 

    public int[] getBaseTiles() 
    { 
     return mActionBaseTiles; 
    } 
} 

public abstract class A<T extends Actions> { 
    A() { 
     doSomething(T.STAND); 
    } 

    protected void doSomething(Actions action) { use action somewhere} 
} 

public class B extends A<SimpleActions> { 
    B() { 
     super(); 
    } 
} 

アクションがnullであるため、AのコンストラクタはdoSomethingのを呼び出したときに、私は常にNullPointerExceptionが取得..

をBが私を拡張するので、 Actions.STANDではなくSimpleActions.STANDを使用することを期待していました。

私は間違っていますか?私はどのようにこれを行う必要がありますか?

+1

スーパークラスのレベルで 'super()'をクラス 'B'から呼び出すと、コンパイラは' T'が 'SimpleActions'ではなく' Actions'を拡張していることを知っています。あなたのアクションに 'Enum'を使うことを考えましたか、それらを"上書き "する必要がありますか?存在する場合、JavaはSmalltalkから期待されるような静的継承を行いません。あなたのコードがそうであるように、あなたの 'Actions'クラスの静的宣言はまったく無意味です。 –

答えて

1

Java言語仕様writes

バウンドT & I1と型変数Xのメンバー...では、交差型(§4.9)T & I1のメンバーである...で型変数が宣言されたポイントに現れます。表現T.STANDActions.STAND、ないSimpleActions.STANDを指し理由です

Actions.STANDSimpleActions.STANDは(非静的メソッドとは異なり、フィールドはオーバーライドすることはできません。)異なる分野ですすでにサブクラスに委譲する1つの方法を強調して

は:アクセサメソッド(ゲッター)を定義しているサブクラスなければなりませんオーバーライド:

abstract class Actions { 
    abstract Actions stand(); 
} 

class SimpleActions extends Actions { 
    private static final Actions STAND = ...; 

    @Override Actions stand() { return STAND;} 
} 

および起動tがTのインスタンスに提供される

t.stand(); 

A工事中です。あるいは、このメソッドを別のタイプ(MotionRegistry?)に移動し、そのインスタンスをAの構築時に提供してください。

あなたのデザインはかなり複雑に見えますが、コードが単純化できるという感覚を揺さぶることはできません(アクションとSimpleActionsの区別が必要ですか?)

+0

ありがとう!メソッドを静的にしても機能しますか? はい、私は、Aを拡張する多くの異なるクラスを持っているので、各クラスには論理的には常に同じですが、グラフィカルに異なる独自のアクションがあります。 –

+0

@Makers_F:いいえ、静的メソッドでは機能しません。静的メソッドのポイントは、メソッドを特定のクラスの実装に結びつけることです。この方法では多態性を利用しますが、これは非静的メソッドでのみ機能します。 – StriplingWarrior

+0

@StriplingWarrior最初はジェネリックスが私を助けてくれたと思っていましたが、私はそれらをもっと使うほど弱くなっています。とてもシームレスなもののために退屈なコードをたくさん書くことに戻る。 –

3

ジェネリックへの型パラメータは、実行時には分かりません。つまり、実行時にはA<Actions>A<SimpleActions>の間に違いはありません。したがって、jvmは、Actions.STANDではなく、SimpleActions.STANDがほしいと言うことができません。実行時に型パラメータを知る必要がある場合は、型パラメータを別の変数に格納する必要があります。

これが明確でない場合は、「実行時のタイプの消去」を参照してください。あなたのコメント次

編集 - あなたが唯一のコンストラクタでこのロジックをやっている場合は 、あなたは、コンストラクタの外で同じロジックが必要な場合は、コンストラクタは

A(Class<? extends Action> actionType){ 
    if(SimpleActions.class.isAssignableFrom(actionType)){ 
     doSomething(SimpleActions.STAND); 
    } 
    else{ 
     doSomething(Actions.STAND); 
    } 
} 

のように見える作ることができ、その後、 Aの内部にClass<? extends Action>タイプのメンバ変数を作成してactionTypeを格納します。

+0

ええ、私はそれについて読む。しかし、どうやって別の変数に入れることができますか? いくつかの(疑似)コードを表示できますか? –

+0

この縫い目はたくさんの作業をしています。さらに、私は多くのアクション実装の王を使用しますので、そうでなければ壁のようになります –

関連する問題