在这本名为《游戏编程模式》的引人入胜的书中,在原型示例中,作者展示了如何使用泛型类在游戏中生成怪物。
免责声明:作者确实声明,该代码只是为了给一个概念的例子(可能不是完美的(
这是给定示例中的C++代码:
class Spawner
{
public:
virtual ~Spawner() {}
virtual Monster* spawnMonster() = 0;
};
template <class T>
class SpawnerFor : public Spawner
{
public:
virtual Monster* spawnMonster() { return new T(); }
};
调用类将运行:
Spawner* ghostSpawner = new SpawnerFor<Ghost>();
我试着把这个例子翻译成C#,这样它就可以在Unity中的一个场景中进行测试:
public class Spawner<T> {
public virtual Monster SpawnMonster() {
return null;
}
}
class SpawnerTemplate<T> : Spawner {
public override Monster SpawnMonster() {
return new T();
}
}
场景中的脚本将运行:
var ghost = new Spawner<Ghost>();
Visual Studio不会编译,所以我重写为:
class SpawnerTemplate<T> : Spawner where T : new(){
public override Monster SpawnMonster() {
return new T() as Monster;
}
}
调用时仍然存在编译错误
var ghost = new SpawnerTemplate<Ghost>();
必须是具有公共无参数构造函数的非抽象类型,才能将其用作参数
这就是Ghost代码的样子:
public class Ghost : Monster
{
public Ghost (int health, int speed) {
this.health = health;
this.speed = speed;
}
public override Monster Clone() {
return new Ghost(health, speed);
}
}
我从C++到C#的翻译正确吗?
谢谢
不确定这个模式在C#中的有用性,但是:
public class Monster
{
}
public class Ghost : Monster
{
}
public abstract class Spawner
{
public abstract Monster SpawnMonster();
}
public class SpawnerFor<T> : Spawner where T : Monster, new()
{
public override Monster SpawnMonster() { return new T(); }
}
然后:
var spawnerForGhost = new SpawnerFor<Ghost>();
var ghost = spawnerForGhost.SpawnMonster();
C#中的最大限制是,您可以为无参数构造函数(, new()
(的存在定义一个约束,如本例所示,但例如,如果您希望new Monster()
作为参数(new Monster(location)
(接收,则它会崩溃(不能对参数构造函数进行约束。您可以在Monster
中明确定义public abstract Initialize(Location location)
,并从SpawnMonster(Location location)
调用它(。