In this fascinating book called Game Programming Patterns, in the Prototype example, the author shows how to use generic class to spawn a monster in a game.
Disclaimer: The author does state that the code is merely for giving an example to a concept (and might not be perfect)
This is the C++ code in the given example:
class Spawner
{
public:
virtual ~Spawner() {}
virtual Monster* spawnMonster() = 0;
};
template <class T>
class SpawnerFor : public Spawner
{
public:
virtual Monster* spawnMonster() { return new T(); }
};
The calling class would run:
Spawner* ghostSpawner = new SpawnerFor<Ghost>();
I've tried to translate this example to C#, so it can be tested in Unity in a scene:
public class Spawner<T> {
public virtual Monster SpawnMonster() {
return null;
}
}
class SpawnerTemplate<T> : Spawner {
public override Monster SpawnMonster() {
return new T();
}
}
The script from within the scene would run:
var ghost = new Spawner<Ghost>();
Visual Studio would not compile and so I rewrote to following:
class SpawnerTemplate<T> : Spawner where T : new(){
public override Monster SpawnMonster() {
return new T() as Monster;
}
}
A compilation error remained when calling:
var ghost = new SpawnerTemplate<Ghost>();
must be a non-abstract type with a public parameterless constructor in order to use it as parameter
This is how the Ghost code looks like:
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);
}
}
Is my translation from C++ to C# is correct?
Thank you
Not sure of the usefulness of this pattern in C#, but:
and then:
The big limitation in C# is that you can define a constraint for the existance of a parameterless constructor (
, new()), as in this example, but if for example you want yournew Monster()to receive as something as a parameter (new Monster(location)), then it breaks down (you can't have constraints for parameterful constructors. You could clearly define apublic abstract Initialize(Location location)inMonsterand call it from theSpawnMonster(Location location)).