2013-12-19 5 views
6

ich eine Basisklasse CollidableObject und ein paar geerbten Klassen namens Player benannt haben, Enemy, InertObject usw.Iterierte durch alle Instanzen der Basisklasse und geerbten Klassen

Ich versuche, eine einfache Möglichkeit zu finden, iterieren durch alle Instanzen von ihnen, so habe ich zunächst eine Liste des Typs CollidableObject erstellt und alle Instanzen der geerbten Klassen in dort.

Die Sache ist, dass wegen der Art des Polymorphismus, wenn ich folgendes

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

Die Draw-Verfahren zu tun, die es nennt, ist die generische Draw-Methode aus der CollidbaleObject Basis, nicht die außer Kraft gesetzt/neues aus die Klasse Player/Enemy/inertObject.

Wie komme ich dazu. Gibt es eine Möglichkeit, eine Sammlung von Objekten aus derselben Baumstruktur zu durchlaufen, deren geerbten Typ beizubehalten?

+2

Ich weiß, das Neben ist, aber es besiegt Art der Punkt, wenn Sie die Methode verschiedene Argumente für jeden Subtyp zu versorgen haben.Wie auch immer, lesen Sie diesen Artikel über übergeordnete Methoden; Sie sollten eine virtuelle Methode haben und das override-Schlüsselwort verwenden, um es zu überschreiben: http://msdn.microsoft.com/en-us/library/ebca9ah3.aspx – Casey

+1

* "nicht die überschriebene/neue aus dem Player/Enemy/inertObject Klasse. "- Welches ist es, überschrieben oder neu? – Harrison

Antwort

9

Gibt es keine Möglichkeit, eine Sammlung von Objekten aus demselben Baum zu durchlaufen, aber ihren geerbten Typ beizubehalten?

Absolut, es gibt einen Weg, das zu tun. Allerdings müssen Sie Ihre Hierarchie in der richtigen Weise einzurichten:

  • Die Draw Methode in den CollidableObject Bedürfnisse virtual
  • Die Draw Methode in den Player Bedürfnisse als override markiert werden markiert.

Dadurch wird sichergestellt, dass der Anruf von Ihrem Beitrag würde die Player ‚s Überschreibung des Verfahrens geführt wird, nicht auf das Verfahren der Basis. Wenn Sie Code sehen, der den dynamischen Typ eines Objekts mit dem Operator is überprüft, wie in if (CollidableObject is Player), sollten Sie einen starken Verdacht erhalten, dass Sie etwas falsch machen. Zum Beispiel können Sie eine double dispatch vermissen.

Wenn Sie nur die richtige Textur für den Typ benötigen, können Sie Texturen in eine Dictionary<Type,Texture> textureForType einfügen und die richtige in Ihrer Schleife mit der GetType() des kollidierbaren Objekts ziehen.

+1

Danke! In Bezug auf die Frage nach dem "Ist" -Operator, warum wäre es in diesem Fall falsch? – user3120072

+1

@ user3120072 Obwohl 'is' nicht automatisch falsch ist, wird es oft anstelle einer besseren Alternative verwendet. Anstatt den dynamischen Typ des Objekts zu überprüfen, könnten Sie beispielsweise eine andere virtuelle Methode aufrufen, die Ihnen die Textur liefert. Die Gefahr, eine Kette von 'if (x ist TypeXyz)' dispatch zu verwenden, besteht darin, dass Sie, wenn Sie einen neuen Typ hinzufügen, jede Stelle suchen müssen, an der Sie eine Kette von 'if (x is ...)' haben und die Behandlung hinzufügen für diesen neuen Typ dort. In einigen Fällen ist das einfach eine Menge Arbeit, aber in anderen Fällen (wenn Sie eine Bibliothek schreiben) ist es einfach unmöglich. – dasblinkenlight

4

Haben Sie versucht:

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

Das funktionierte, aber würde ich mit dieser Methode Informationen verlieren? – user3120072

+0

@ user3120072 - nicht klar, welche "Informationen" Sie besorgt sind? Wenn Sie denken, dass '(Player)' cast neues Objekt erzeugt, als Ihre Annahme falsch ist, erzeugt cast keine neuen Objekte, sondern zwingt dazu, auf Objekt als anderen Typ zu verweisen (es wird auch eine Laufzeitprüfung geben, um sicherzustellen, dass Cast möglich ist) . –

-1

Ich würde jede Klasse eine Draw-Methode implementieren, die zu dieser Klasse spezifisch ist. Sie würden alle die gleiche Unterschrift brauchen.

Dann wird Ihr foreach kümmert sich nicht darum, welche Klasse es tatsächlich ist, und wie dies

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

es Dies wäre die „Object Oriented“ Art und Weise zu tun, aussehen würde.

+2

Dies ist, was das OP bereits tut, aber sie verwenden wahrscheinlich virtual/override nicht richtig, wie in der Antwort von @dasblinkenlight beschrieben – Scampbell