2013-12-19 10 views
6

継承したクラスを反復処理し、EnemyPlayerInertObjectという名前継承したクラスのカップルなどすべての基底クラスのインスタンスと私は、基本クラスが<code>CollidableObject</code>名付けてい

は私が反復する簡単な方法を見つけようとしていますそれらのすべてのインスタンスを通して、私は最初にタイプCollidableObjectのリストを作成し、そこに継承されたクラスのすべてのインスタンスを配置しました。私はそれがCollidbaleObjectベース、ないから上書き/新しいものからジェネリックDrawメソッドで呼び出すdrawメソッド

foreach (CollidableObject CollidableObject in collidableObjects) 
{ 
    if (CollidableObject is Player) 
    { 
    CollidableObject.Draw(spriteBatch, testPlayerTexture); 
    } 
    // Then the same prodedure for each type of CollidableObject. 
    // Might change to switch or something.        
} 

次の手順を実行したときに

事は、そのために多型の性質のものですPlayer/Enemy/inertObjectクラスです。

これを回避するにはどうすればよいですか。同じツリーのオブジェクトのコレクションを反復する方法はありますか?継承された型を維持していますか?

+2

私はこれが付随的であることを認識していますが、各サブタイプに異なる引数を指定する必要がある場合は、この点を克服するのは難しいことです。とにかく、メソッドのオーバーライドについてこの記事をチェックしてください。仮想メソッドを持ち、overrideキーワードを使ってそれをオーバーライドする必要があります:http://msdn.microsoft.com/en-us/library/ebca9ah3.aspx – Casey

+1

* "Player/Enemy/inertObjectからのオーバーライド/新規のものではありませんクラス* " - どちらが優先され、上書きされるか、新しいものか? – Harrison

答えて

9

継承された型を維持しながら同じツリーのオブジェクトのコレクションを反復処理する方法はありませんか?

絶対に、それを行う方法があります。しかし、あなたは正しい方法であなたの階層を設定する必要があります。

  • virtual
  • overrideとしてマークするPlayerニーズのDrawメソッドをマークするCollidableObjectニーズのDraw方法。

このはあなたのポストからの呼び出しがないベースの方法に、方法のPlayerのオーバーライドにルーティングされることを保証します。

is演算子を使用してオブジェクトの動的型をチェックするコードが表示される場合は、if (CollidableObject is Player)のように、間違ったことを強く疑う必要があります。たとえば、double dispatchが不足している可能性があります。

タイプの適切なテクスチャが知りたい場合は、Dictionary<Type,Texture> textureForTypeにテクスチャを置き、ループ可能オブジェクトのGetType()を使用してループ内の正しいものを引き出します。

+1

ありがとう!この "is"演算子については、どうしてこの場合に間違っているのでしょうか? – user3120072

+1

@ user3120072 'is'は自動的に間違っているわけではありませんが、より良い代替手段の代わりによく使われます。たとえば、オブジェクトの動的型をチェックするのではなく、テクスチャを与える別の仮想メソッドを呼び出すことができます。 'if(x is TypeXyz)'ディスパッチの連鎖を使う危険性は、新しい型を追加するときに 'if(x is ...)の連鎖を持つすべての場所を見つけて処理を追加する必要がありますその新しいタイプのために。いくつかのケースでは、それは単純に多くの作業ですが、他の場合(ライブラリを書くとき)は単純に不可能です。 – dasblinkenlight

4

あなたが試してみました:

foreach (CollidableObject CollidableObject in collidableObjects) 
{ 
    if (CollidableObject is Player) 
    { 
     ((Player) CollidableObject).Draw(spriteBatch, testPlayerTexture); 
    }  
    //Then the same prodedure for each type of CollidableObject. Might change to switch or something.        
} 
+0

これはうまくいったが、私はこの方法で情報を失うだろうか? – user3120072

+0

@ user3120072 - あなたが心配している「情報」は何ですか?キャストが新しいオブジェクトを作成するのではなく、オブジェクトを別の型として参照するように強制します(キャストが可能であることを確認するランタイムチェックもあります) 。 –

-1

を、私は、各クラスは、そのクラスに固有のDrawメソッドを実装する必要があります。彼らはすべて同じ署名が必要です。

次に、あなたのforeachのは、それが実際にどのクラスを気にせず、これはそれを行うための「オブジェクト指向」の方法でしょう。この

foreach (CollidableObject CollidableObject in collidableObjects) 
{ 
     CollidableObject.Draw(....);           
} 

ようになります。

+2

これはOPがすでにやっていることですが、@dasblinkenlightの回答に記載されているように、バーチャル/オーバーライドを正しく使用していない可能性があります – Scampbell

関連する問題