我有抽象基类。
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
的上下文中执行此操作,这些CurrentPlayer
和PlayingField
是ITicTacToePlayer
和TicTacToeGameField
类型而不使用每个显式转换时间?
答案 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;
....
}
只需在内部实现中使用这些属性。