问题描述
在这本名为 Game Programming Patterns 的引人入胜的书中,在 Prototype 示例中,作者展示了如何使用泛型类在游戏中生成怪物。
免责声明:作者确实声明该代码仅用于举例说明一个概念(可能并不完美)
这是给定示例中的 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)
),然后它会崩溃(您不能对参数构造函数进行约束。您可以在 public abstract Initialize(Location location)
中明确定义一个 Monster
并从 {{ 1}}).