为了娱乐,我正在编写一个通用的棋盘游戏类,可以针对各种游戏进行量身定制。它包括许多常规功能(填写单元格,旋转,翻转,应用移动列表等)。
基类是通用的,因此您可以指定每个单元格应填充的内容。
public class Board<T> { /* various usefule routines that return new instances of Board<T> */ }
我从一个TicTacToe游戏开始,声明如下:
public enum TicTacMove { Empty, X, O };
public class TicTacToe : Board<TicTacMove> { /* ... */ }
我遇到麻烦的地方是将基本例程返回的通用版本转换回派生类-我根本做不到。
当我尝试将基函数的值分配给派生类时,我得到:
错误CS0266无法将类型'BoardGames.Board'隐式转换为'BoardGames.TicTacToe.TicTacToe'。存在显式转换(您是否缺少演员表?)
因此,我明确地将其强制转换,然后给了我一个InvalidCastException:
无法转换类型为'BoardGames.Board`1 [BoardGames.TicTacToe.TicTacMove]'的对象来键入'BoardGames.TicTacToe.TicTacToe'
如果我的班级拥有可变数据,我可以简单地更改数据而不用担心;我的问题是如何通过返回一个新实例以使每个实例不可变来实现这一目标。
编辑: 例如,基类具有以下构造函数:
public Board(Board<T> Source, IEnumerable<(int Index, T Value)> Changes)
从派生类TicTacToe调用此构造函数不会产生TicTacToe的新实例,而是会产生Board的实例,然后不能将其转换回TicTacToe。
答案 0 :(得分:0)
好的,我知道了。
由于不允许您从基类强制转换回派生类,因此必须将返回新实例的函数称为派生构造函数的基类构造函数。
为简化起见,我在基类中创建了一个构造函数,该构造函数返回修改后的实例。
在派生类中,我实现了一个私有的构造函数,该构造函数接受要进行的更改的列表。这样做的好处是几乎是样板。
然后,每个派生类都可以调用自己类型的构造函数,该构造函数随后将工作传递给基类构造函数。这样可以避免我遇到的投放问题。
作为一个例子(前面是伪代码)
public abstract class BaseClass {
protected BaseClass(BaseClass Source, var changes...) ...
}
public class DerivedClass {
private DerivedClass(DerivedClass Source, var changes)
: BaseClass(Source, changes) { }
public DerivedClass MakeChange(var change) {
...set up changed values...
return new DerivedClass(this, changes)
}
}