如何正确设置继承属性的类型

时间:2017-01-11 15:25:13

标签: c# oop inheritance types type-conversion

我有抽象基类。

public abstract class TurnBasedGameReferee
{
    public ITurnBasedGamePlayer CurrentPlayer { get; private set; }
    public TurnBasedGameField PlayingField { get; protected set; }
    /*snipped*/
}

我继承了班级:

public class TicTacToeReferee : TurnBasedGameReferee { /*snipped*/ }

在TicTacToeReferee中我应该引用这样的属性:

(ITicTacToePlayer)this.CurrentPlayer;
(TicTacToeGameField)this.PlayingField;

我认为,每次在这里使用显式转换都是不正确的。

有没有办法在TicTacToeReferee的上下文中执行此操作,这些CurrentPlayerPlayingFieldITicTacToePlayerTicTacToeGameField类型而不使用每个显式转换时间?

2 个答案:

答案 0 :(得分:2)

你可以使用泛型。

public abstract class TurnBasedGameReferee<TPlayer, TField>
                  where TPlayer : ITurnBasedGamePlayer 
                  where TField : TurnBasedGameField 
{
    public TPlayer CurrentPlayer { get; private set; }
    public TField PlayingField { get; protected set; }
    /*snipped*/
}

public class TicTacToeReferee : TurnBasedGameReferee<ITicTacToePlayer, TicTacToeGameField>

它假设,ITicTacToePlayer继承自ITurnBasedGamePlayer的{​​{1}}和TicTacToeGameField,但我认为这就是您的意思。

答案 1 :(得分:1)

基于Maksim Simkin's回答以及您的评论可以强制执行您想要的类型安全,但代价是额外的通用类型参数并增加了解决方案的复杂性:

public interface ITurnBasedGame { }
public interface ITurnBasedGamePlayer<TGame> where TGame : ITurnBasedGame { }
public abstract class TurnBasedGameField<TGame> where TGame : ITurnBasedGame { }

public abstract class TurnBasedGameReferee<TGame, TPlayer, TField>
    where TGame: ITurnBasedGame
    where TPlayer: ITurnBasedGamePlayer<TGame>
    where TField: TurnBasedGameField<TGame>
{
    public TPlayer CurrentPlayer { get; private set; }
    public TField PlayingField { get; protected set; }
}

现在,考虑以下类型:

public class TicTacToeGame : ITurnBasedGame { }
public class TicTacToePlayer : ITurnBasedGamePlayer<TicTacToeGame> { }
public class TicTacToeGameField : TurnBasedGameField<TicTacToeGame> { }
public class ChessGame : ITurnBasedGame { }
public class ChessPlayer : ITurnBasedGamePlayer<ChessGame> { }
public class ChessGameField : TurnBasedGameField<ChessGame> { }

以下是编译时错误:

public class TicTacToeReferee: TurnBasedGameReferee<TicTacToeGame, ChessPlayer, ChessGameField> { }

所有这一切,这肯定是不值得的,只是为了避免将接口转换为类的具体类型。如果您不喜欢所有演员表,那么您可以随时实现私有帮助器属性来清理代码:

public class TicTacToeReferee : TurnBasedGameReferee
{
     private TicTacToePlayer CurrentTicTacToePlayer => CurrentPlayer as TicTacToePlayer;
     private TicTacToeGameField TicTacToePlayingField => PlayingField as TicTacToeGameField;
     ....
}

只需在内部实现中使用这些属性。