【发布时间】:2020-12-28 16:05:55
【问题描述】:
在这本引人入胜的名为 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# 的翻译是否正确?
谢谢
【问题讨论】:
-
你能提供你的 Ghost 类的样子吗?我怀疑您没有定义公共 Ghost() 构造函数。
-
您确定
Ghost继承自Monster(其中Monster在C# 中可能是一个接口)?同样在 C# 中,我相信有一种方法可以指定您的泛型必须遵守某个接口。所以你可能会说class SpawnerTemplate<T> where T : Moster。 -
我在问题中添加了 Ghost 类。 Monster 是一个基类(但目前不是抽象的)。这种代码架构背后的逻辑称为模板。我不确定将 SpawnerTamplate T 更改为 Monster,它应该是什么,因为 SpawnerTemplate 是 Spawner 类的模板。我想。
标签: c# c++ class generics prototype-programming