2016-04-24 120 views
2

我正在創建一個國際象棋遊戲,我已經創建了白嘴鴉和主教,我即將開始創建女王棋子。問題在於女王結合了白嘴鴉和主教的動作,所以我不想寫出重複的代碼,而只是使用2個類作爲白嘴鴉和主教的代碼,而他們的方法進入後者。如何將2個類中的2個方法合併爲1個基類?

這裏的主教類

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

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

的車類是基本一致的,但不同的實施GetValidTurns()

在我的項目每一件繼承它包含的信息,每一塊Figure抽象類正在使用的唯一區別是在​​方法中,所以我們讓派生類去實現它。

那是女王級

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

回答

1

您可以創建一個新的類或接口來進行有效轉換,以封裝它們並使其易於重用。

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); 
    } 
} 

此外,原始類中的代碼應由新的ValidTurn類替換。

編輯:

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

也許你可以考慮把所有的驗證邏輯到ValidTurn(TurnValidation)。

+0

我不能在那裏實現有效的車輪轉彎,因爲它們還必須繼承'圖'類,因爲它包含基本函數來檢查轉彎是否有效。 – PreqlSusSpermaOhranitel

+0

您可以使用ValidTurns構造函數或函數參數傳遞Figure類。也許你想把你的輪迴驗證的其他邏輯也放在這個ValidTurn類中(參見單一責任原則)。 – natschz

+0

你能編輯你的答案,所以你可以告訴我該怎麼做?我正在討論帶參數 – PreqlSusSpermaOhranitel

2

也許你可以來得這麼一種不同的方式。

有一個抽象基類,它定義一招:

public abstract class Move 
{ 
    // Whatever 
} 

然後導出不同於移動,例如:

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

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

public sealed class KnightsMove : Move 
{ 
} 

public sealed class KingsMove : Move 
{ 
} 

然後,可以使用組合物相結合的不同的動作:

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()}; 
} 

Move類可以聲明如下S:

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

其中Position是定義來保存關於在基板上的位置(其可以是如剛剛X,Y COORDS簡單)信息的另一類,並且Board是保持約在所有的信息的類棋子在棋盤上。

然後PossibleMoves()的實現將返回枚舉所有可能的移動類型,從給定的位置開始並且處於給定狀態的棋盤。

+0

這看起來很整齊,但我是初學者,我不太清楚我應該把什麼放在抽象類Move中。如果您可以使用虛擬方法提供一些示例代碼:因爲據我所知,密封的類只有一種方法,那就沒有別的了,那麼爲什麼不把它們變成自己的方法呢? – PreqlSusSpermaOhranitel

+0

密封只能防止遺傳,你會分裂它,所以你可以重用你的回合代碼(如你所願)。 https://en.wikipedia.org/wiki/Single_responsibility_principle – natschz

+0

我知道什麼是密封類,我的意思是說,他們將只包含一種方法 – PreqlSusSpermaOhranitel

0

如果你是初學者,爲什麼不把一些簡單的方法放在你的基類中?

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); 

    } 
} 

然後派生類可以只是重新利用各自GetValidTurns內這些方法構建的移動返回列表。編輯:即使你是初學者,我建議在這裏離開Tuple並創建一個簡單的「點」類或結構。它會使你的代碼更具可讀性,即使對你自己也是如此。

+0

的構造函數。但是,將其作爲靜態函數實現可能不是最好的操作。但我同意你的元組可能會更好會像「bool IsValidTurn(圖,int x,int y)」 – natschz

+0

這些不會是靜態函數,但在您的圖基類內的受保護的方法。重用基類功能並不是糟糕的OOP。你基本上將把有效的舉措從個人作品中分離出來,變成一種更通用的方法。你可以用更復雜的方式對它進行建模,但這不是一個靜態方法的列表:) –

+0

好吧,這看起來更好,但也有一個類的圖和轉向驗證,這種違反單一責任原則? – natschz