2016-04-24 5 views
2

Ich erstelle ein Schachspiel, ich habe bereits die Turmspitzen und die des Bischofs erstellt und ich beginne gerade damit, das Königinstück zu erschaffen. Das Problem ist, dass die Dame die Züge des Turms und des Bischofs kombiniert, also möchte ich keinen repetitiven Code schreiben und stattdessen nur die 2 Klassen für Turm und Läufer verwenden und sie sind Methoden in die Dame eins.Wie kombiniert man 2 Methoden aus 2 Klassen, die von 1 Base abgeleitet sind?

Hier ist der Bischof Klasse

public class OficerPiece : Figure 
{ 
    public OficerPiece(FigureDefinition definition) : base(definition) 
    { 
    } 

    protected override List<Tuple<int, int>> GetValidTurns() 
    { 
     //here i set the valid moves 
    } 
} 

Die Saatkrähe Klasse im Grunde das gleiche, aber mit unterschiedlichen Umsetzung der in meinem Projekt GetValidTurns()

Jedes einzelne Stück erbt die Figure abstrakte Klasse ist die Info, dass jedes Stück enthält verwendet den einzigen Unterschied ist in der Methode, so dass wir das für die abgeleitete Klasse zu implementieren lassen.

, dass die Königin Klasse

public class Kralica : Figure 
{ 
    public Kralica(FigureDefinition definition) : base(definition) 
    { 
    } 

    protected override List<Tuple<int, int>> GetValidTurns() 
    { 
     //here i want to combine the 2 methods GetValidTurns from the bishop class and the rook class 
    } 
} 

Antwort

1

Sie können eine neue Klasse oder Schnittstelle für Ihre gültigen Abbiegungen erstellen, um sie zu kapseln und die Wiederverwendung zu vereinfachen.

public interface ValidTurn 
{ 
    List<Tuple<int, int>> GetValidTurns(); 
} 

public class StraightSlide : ValidTurn 
{ 
    public List<Tuple<int, int>> GetValidTurns() 
    { 
     // ... valid rook turns here 
    } 
} 

public class DiagonalSlide : ValidTurn 
{ 
    public List<Tuple<int, int>> GetValidTurns() 
    { 
     // ... valid bishops turns here 
    } 
} 

public class Kralica : Figure 
{ 
    public Kralica(FigureDefinition definition) : base(definition) 
    { 
    } 

    protected override List<Tuple<int, int>> GetValidTurns() 
    { 
     var straight = new StraightSlide(); 
     var diagonal = new DiagonalSlide(); 

     return straight.Concat(diagonal); 
    } 
} 

Auch der Code in Ihren ursprünglichen Klassen sollte durch Ihre neuen ValidTurn-Klassen ersetzt werden.

Edit:

public class StraightSlide : ValidTurn 
{ 
    private Figure figure; 
    public StraightSlide(Figure figure) 
    { 
     this.figure = figure; 
    } 

    public List<Tuple<int, int>> GetValidTurns() 
    { 
     figure.YourMethodToCall(); 
     // ... valid rook turns here 
    } 
} 

könnten Sie halten vielleicht alle Logik Ihre Validierung setzen in die ValidTurn (TurnValidation).

+0

Ich kann zum Beispiel dort die gültigen Turmdrehungen nicht implementieren, weil sie auch von der Klasse 'Figure' erben müssen, da sie wesentliche Funktionen enthält, um zu überprüfen, ob eine Runde gültig ist. – PreqlSusSpermaOhranitel

+0

Sie können die Figure-Klasse mit dem ValidTurns-Konstruktor oder mit den Funktionsparametern übergeben. Und vielleicht möchten Sie auch in dieser ValidTurn-Klasse die andere Logik Ihrer Runde validieren (siehe Prinzip der Einzelverantwortung). – natschz

+0

Können Sie Ihre Antwort bearbeiten, damit Sie mir zeigen können, wie das geht? Ich spreche über den Konstruktor mit dem Parameter – PreqlSusSpermaOhranitel

2

ist könnte Sie vielleicht auf diese kommen, eine andere Art und Weise.

Haben sie eine abstrakte Basisklasse, die eine Bewegung definiert:

public abstract class Move 
{ 
    // Whatever 
} 

Und dann ableiten verschiedene Bewegungen aus, dass zum Beispiel:

public sealed class Diagonal : Move // Bishop, Queen 
{ 
} 

public sealed class Orthongonal : Move // Rook, Queen 
{ 
} 

public sealed class KnightsMove : Move 
{ 
} 

public sealed class KingsMove : Move 
{ 
} 

Dann können Sie die verschiedenen Bewegungen mit Zusammensetzung kombinieren:

public class Kralica : Figure 
{ 
    public Kralica(FigureDefinition definition) : base(definition) 
    { 
    } 

    protected override List<Move> GetValidTurns() 
    { 
     return moves; 
    } 

    readonly List<Move> moves = new List<Move> {new Diagonal(), new Orthongonal()}; 
} 

Ihre Klasse könnte wie folgt deklariert werden s:

public abstract class Move 
{ 
    public abstract IEnumerable<Position> PossibleMoves(Position start, Board board); 
} 

wo Position andere Klasse ist definiert Information über eine Position auf dem Brett zu halten (die so einfach sein kann wie gerade X, Y Koordinaten) und Board ist eine Klasse, die Informationen über in dem alle hält Stücke sind auf dem Brett.

Dann würde eine Implementierung von PossibleMoves() eine Aufzählung aller möglichen Bewegungen für diesen Typ ab der gegebenen Position und mit der Karte im gegebenen Zustand zurückgeben.

+0

Das scheint ziemlich ordentlich, aber ich bin Anfänger und ich bin nicht ganz sicher, was ich in die abstrakte Klasse Move setzen sollte. Wenn Sie einen Beispielcode mit virtuellen Methoden zur Verfügung stellen können:? Weil, soweit ich verstehe, die versiegelten Klassen nur eine Methode in sich haben und das ist nichts anderes, warum also nicht in Methoden selbst verwandeln? – PreqlSusSpermaOhranitel

+0

Sealed verhindert nur die Vererbung und Sie würden es aufteilen, so dass Sie Ihren Turn-Code wiederverwenden können (wie Sie möchten). https://en.wikipedia.org/wiki/Single_responsibility_principle – natschz

+0

Ich weiß, was versiegelte Klasse bedeutet ich, dass sie nur 1 Methode enthalten wird – PreqlSusSpermaOhranitel

0

Wenn Sie ein Anfänger sind, warum nicht einige einfache Methoden in Ihre Basisklasse einfügen Abbildung, die Verschiebungen zu Ihrer Punktliste hinzufügt?

public class Kralica : Figure 
    { 
     protected Tuple<int, int> Position {get; set;} 

     public Kralica(FigureDefinition definition) : base(definition) 
     { 
     } 

     protected override List<Tuple<int, int>> GetValidTurns() 
     { 
      //here i want to combine the 2 methods GetValidTurns from the bishop class and the rook class 
     } 

     protected void AddDiagonalMoves(List<Tuple<int, int>> moves) 
     { 
      diagonalMoves = new List<Tuple<int, int>>(); 

      // calculate diagonal moves from my piece position which should be a member property here 

      moves.AddRange(diagonalMoves); 
     } 
    } 


public class Kralica : Figure 
{ 
    public Kralica(FigureDefinition definition) : base(definition) 
    { 
    } 

    protected override List<Tuple<int, int>> GetValidTurns() 
    { 
     var movesThisTurn = new List<Tuple<int, int>>(); 
     //here i want to combine the 2 methods GetValidTurns from the bishop class and the rook class 
     base.AddDiagonalMoves(movesThisTurn); 
     base.AddLinearMoves(movesThisTurn); 

    } 
} 

Dann abgeleiteten Klassen konnten nur jene Methoden innerhalb ihrer jeweiligen GetValidTurns erneut verwenden, um die Liste der Züge Gebäude zurückzukehren.

Editorial: Auch wenn Sie ein Anfänger sind, empfehle ich, weg von der Tuple hier und erstellen Sie eine einfache "Point" -Klasse oder Struktur. Es wird Ihren Code viel lesbarer machen, sogar für Sie selbst.

+0

Aber die Implementierung dieser als statische Funktionen möglicherweise nicht die beste Praxis oop. Aber ich stimme dir zu, die Tupel vielleicht besser wäre etwas wie "Bool IsValidTurn (Abbildung Abbildung, int x, int y)" – natschz

+0

Dies wäre nicht statische Funktionen, sondern geschützte Methoden innerhalb Ihrer Figur Basisklasse. Die Wiederverwendung der Basisklassenfunktionalität ist keine schlechte OOP. Sie würden im Wesentlichen die gültigen Bewegungen von den einzelnen Stücken in einen allgemeineren Ansatz loslösen. Du könntest es auf komplexere Weise sicherlich modellieren, aber das ist keine Liste von statischen Methoden :) –

+0

Ok, das sieht besser aus, aber es gibt auch die Zahlen und die Validierung in einer Klasse und diese Art verletzt das Prinzip der Verantwortlichkeit? – natschz

Verwandte Themen