2016-04-24 47 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