Die parent Class als "Container" für alle child Klassen nehmen?



  • Hey Leute,

    Habe folgende Problemstellung bzw. Unsauberkeit im Code die ich gerne anders lösen würde.

    public void EndTurn(List<Infantry_Unit> player_inf) 
            {
                foreach(var item in player_inf)
                {
                    item.moveable = true;
                }
            }
    

    Im folgenden Code habe eine Liste mit den Parametern einer Liste vom Typ Infantry Units.

    "Infrantry Units" eerbt von der Klasse "Unit".
    von Units erben ebenfalls "Armored Units" & "Support Units"

    Nun habe ich den Versuch gestartet den Code so umzuschreiben:

    public void EndTurn(List<Unit> player_inf) 
            {
                foreach(var item in player_inf)
                {
                    item.moveable = true;
                }
            }
    

    Leider funktioniert das Ganze nicht so wie ich das möchte, lauter Fehlermeldungen. Es geht halt darum das ich dieser Methode 3 verschiedene Parameter zukommen lassen möchte, ohne vielleicht Überladungen der Methoden zu erstellen.

    Ich dachte demnach wenn ich die Klasse List direkt mit der ParentKlasse als Attribut deklariere würde es möglich sein die Child Klasse als Parameter zu übergeben?

    Hoffe ihr versteht meine Frage !

    gruß Charlie



  • Falke88 schrieb:

    Hoffe ihr versteht meine Frage !

    Nicht wirklich, dazu fehlt mir auch die Info, welche Fehlermeldungen erzeugt werden.

    Wenn Infantry_Unit von Unit abgeleitet ist und der Member "moveable" in Unit deklariert ist, kann man schon eine List machen, dort alle "Sorten" von Units reinschmeißen und dann abarbeiten.



  • Gut ich versuche es mit einem anderen Beispiel.

    Hierarchie:

    Unit -> Infantry_Unit, Armored_Unit, Support_Unit

    Hier beerbt Unit alle 3 Child Klassen.

    void Transition(Unit unit)
            {
                if (unit.selected && unit.moving)
                {
                    float step_x = (unit.targetPosition.X - unit.unitIcon.Position.X) / 50;
                    float step_y = (unit.targetPosition.Y - unit.unitIcon.Position.Y) / 50;
    
                    if ((step_x > 0.01f || step_y > 0.01f) || (step_x < -0.01f || step_y < -0.01f))
                        unit.unitIcon.Position = new Vector2f(unit.unitIcon.Position.X + step_x, unit.unitIcon.Position.Y + step_y);
                    else
                        unit.unitIcon.Position = new Vector2f(unit.targetPosition.X, unit.targetPosition.Y);
    
                }
            }
    

    Die ist eine Methode die ich mit folgenden Möglichkeiten aufrufen möchte:

    Transition(Infantry_Unit)
    Transition(Armored_Unit)
    Transition(Support_Unit)

    Die Member wie z.b. iconUnit, targetPosition, selected und moving sind bei VS rot markiert d.h. es gibt keine Definition. Das liegt daran das diese Member keine abstracten Member von Unit sondern konkrete Member von den Child Klasse sind.

    Ich gehe halt grünohriger Weise davon aus das die Übergabe eines Arguments aus dem Bereich der Child Klassen (z.b. Infantry_Unit) ausreichen müsste.

    Da aber schon bei der Methoden Deklaration Fehler aufgeworfen werden im Bezug auf Definitionen der Member. Brauche ich den Aufruf der Methode mit einem Parameter ala Infantry_Unit garnicht erst ausführen.

    natürlich könnte man mir jetzt die Möglichkeit mit überladenen Methoden anzeigen, jedoch habe ich irgendwie das Gefühl es müsste auch mit Parent Klassen als Parameter funktionieren oder?



  • Das sind aber Grundlagen der Objektorientierung - packe die Member in die Basisklasse, anders geht es nicht (ansonsten müsstest du ja in den abgeleiteten Klassen jeweils diese Member haben - und das wäre dann 'Codebloat').

    Nachtrag: Die Member solltest du dann als Eigenschaften (properties) zur Verfügung stellen (anstatt direkt dann mit den Klassenvariablen zu arbeiten).
    Für die meisten Eigenschaften reichen ersteinmal die "automatic properties", z.B.

    bool Moveable { get; private set; }
    

    "private" für den Setter, damit man von außerhalb nur lesen kann.



  • Jau danke für den Deutschuss!

    Ich bin noch relativ skeptisch mit dem Umgang mit Properties. Inwiefern können diese mir überhaupt hier von nutzen sein, sie bieten eine Sicherheit an - aber brauche ich das denn bei nem kleinen Game Project? Oder sollte man sich einfach dran gewöhnen die zu nutzen



  • Falke88 schrieb:

    Oder sollte man sich einfach dran gewöhnen die zu nutzen

    Du solltest Properties bevorzugen, wo es nur geht - und es geht fast immer 😉
    Neben der zusätzlichen Abstraktion (die dir vllt. erst später gelegen kommt) bieten sie auch andere Vorteile. Sie sind für DataBinding geeignet und sie arbeiten besser mit Reflection zusammen.

    Spontan fällt mir nur ein Nachteil von Properties ein: Man kann sie nicht direkt als out/ref Parameter an andere Funktionen übergeben. Da muss man mit einer Hilfsvariable arbeiten.



  • Kann man ne Property nicht als Parameter übergeben? wenn "get" doch ohne zugriffsmodifizierer also implizit public (denke mal das dies so bei VS / C# der Fall ist) deklariert ist, dürfte man doch über den Property Bezeichner als Argument das Ganze übergeben können?

    Oder meinst du was anderes



  • Falke88_tmp schrieb:

    Kann man ne Property nicht als Parameter übergeben? wenn "get" doch ohne zugriffsmodifizierer also implizit public (denke mal das dies so bei VS / C# der Fall ist) deklariert ist, dürfte man doch über den Property Bezeichner als Argument das Ganze übergeben können?

    Oder meinst du was anderes

    Du kannst eine Property natürlich als Parameter übergeben. Nur nicht als out/ref-Parameter.



  • Lies genauer 😉
    Es geht um die out / ref Parameter, also z.B. ist folgendes nicht möglich:

    DoSomething(ref Moveable);
    

    sondern nur

    bool moveable = Moveable;
    DoSomething(ref moveable);
    Moveable = moveable;
    

    Aber ref und out sollte man sowieso nur sehr sparsam einsetzen - z.B. bei den TryParse-Methoden, da der Rückgabewert mit dem Erfolg des Parsens schon belegt ist.

    Edit: too late, too late



  • Ha ok mit out/ref bin ich noch nicht in Berührung gekommen, ich festige immer gerne neu erlerntes mit eigenen Projekten. Umso faszinierender sind neue Tricks die cih dann in neuen Projekten anwenden kann. Ist n ziemlich gutes Prinzip für festen Lernerfolg 😉



  • public void EndTurn<T>(IEnumerable<T> units) // warum nicht static?
        where T : Unit // oder gleich ein Interface IUnit machen
    { 
        foreach(var u in units) 
            u.moveable = true; 
    }
    

    Hm?
    Wobei das rumfummeln in den Innereien einer Klasse sowieso nicht schön ist.
    Also warum nicht gleich

    public static void EndTurn<T>(IEnumerable<T> units)
        where T : IUnit
    { 
        foreach(var u in units) 
            u.EndTurn();
    }
    

    ?



  • hustbaer schrieb:

    public void EndTurn<T>(IEnumerable<T> units) // warum nicht static?
        where T : Unit // oder gleich ein Interface IUnit machen
    { 
        foreach(var u in units) 
            u.moveable = true; 
    }
    

    Hm?
    Wobei das rumfummeln in den Innereien einer Klasse sowieso nicht schön ist.
    Also warum nicht gleich

    public static void EndTurn<T>(IEnumerable<T> units)
        where T : IUnit
    { 
        foreach(var u in units) 
            u.EndTurn();
    }
    

    ?

    Wie bezeichnet man diese Vorgehensweise - möchte mich da erstmal einlesen bevor ich das blindlinks verwenden. Sieht auf jedenfalls nach dem aus was ich suche! 🕶



  • Falke88 schrieb:

    Wie bezeichnet man diese Vorgehensweise

    Äh. Programmieren?

    Ne, weiss nicht, was genau meinste? Die Generics (die <T> Sache)? Oder die Verwendung eines Interfaces? ...?



  • Ha ne meinte schon das mit den Generics. kenne das keyword where noch nicht.

    Sieht so aus als könnte man in der Methoden Deklaration für jede "where" Bedingung die zutrifft einen anderen Anweisungsblock reinpowern. Ähnlich wie ne Switch Anweisung?



  • Nein. Das where ist ein Type-Constraint, welches auf den Typ T abzielt.
    Siehe dazu http://msdn.microsoft.com/en-us/library/bb384067.aspx



  • Sorry das ich gerade zu faul bin den Link zu folgen 😛

    Aber ein Constraint ist eine Einschränkung richtig? D.h für <T> können nur die Möglichkeiten die bei "where" definiert sind angegeben werden?



  • Nein.
    Aber das googelst du dir bitte selbst.


Log in to reply