Search code examples
c#unity-game-enginecommandcommand-pattern

Extract inherited class argument from constructor


first of all sorry if I'll be using a messy terminology, I'm still learning a lot about the Command pattern and C#.

I'm trying to implement the command pattern in Unity3D using C#, specifically this implementation readapted to my case.

Given the Command.cs and the GameController.cs scripts, I've created a DoThing class, inheriting from the Command class, implemented with the following code:

public class DoThing : Command
{
    public string name;
    public int healthPoints;

    public DoThing(string name, int healthPoints)
    {
        this.name = name;
        this.healthPoints = healthPoints;
    }
}

Now, since I passed some arguments to the Commands through a constructor (name, healthPoints), I'd want to extract those from another script.

I tried (successfully) to pass the arguments to a command in the following line and to save the command in a stack:

var doCommand = new DoThing("asdf", 123);
Stack<Command> listOfCommands = new Stack<Command>();
listOfCommands.Push(doCommand);

And I tried (successfully) retrieving those arguments in the watch window, during code execution:

listOfCommands.Peek().name //returns "asdf"

But then this doesn't work in the script, meaning that the arguments can't be seen:

Debug.Log(listOfCommands.Peek().name) //throws error

is there a way to extract the argument?


Solution

  • Since your listOfCommands is a Stack of Command, listOfCommands.Peek() returns a Command which does not have the name variable. You have to check the type of the variable returned by the function and cast it before accessing the variable.

    Command command = listOfCommands.Peek();
    if(command is DoThing)
    {
        Debug.Log(((DoThing) command).name);
    }
    

    or more compact

    if(listOfCommands.Peek() is DoThing doThing)
    {
        Debug.Log(doThing.name);
    }
    

    or

    DoThing doThing = listOfCommands.Peek() as DoThing;
    if(doThing != null)
    {
        Debug.Log(doThing.name);
    }