Reputation: 107
to keep things simple I have two classes: ActionTaken
and MovementTaken
. MovementTaken
is a derived class from ActionTaken
. I have a Queue
full of actions, and each action has a char
that determines the type of action. (Every action has a correct type) I want to pass elements of the Queue
to a function, that works specifically with a MovementTaken
parameter, but since I'm using polymorphism the parameter is of type ActionTaken
, but then I cannot use member variables from MovementTaken
, but don't exist in ActionTaken
. But if I set the function activateMovement
's parameter to type MovementTaken
, I believe there would be an error, saying you cannot convert a base type to a derived type. Here's the code:
public abstract class ActionTaken : MonoBehaviour
{
public char type;
public Transform minionTakingAction;
}
public class MovementTaken : ActionTaken
{
public int targetTileH;
public int targetTileV;
public MovementTaken(Transform _minionTakingAction, int _targetTileH, int _targetTileV)
{
type = 'M';
minionTakingAction = _minionTakingAction;
targetTileH = _targetTileH;
targetTileV = _targetTileV;
}
}
Queue<ActionTaken> actionTaken;
public void activateMovement(ActionTaken toActivate)
{//some code using toActivate's members targetTileH and targetTileV}
Upvotes: 2
Views: 981
Reputation: 3178
The advantage of Abstract
classes is defining base implementation, or to force derived types into implementation details:
public abstract class ActionTaken : MonoBehaviour
{
public char Type { get; protected set; }
public Transform Target { get; }
// base ctor
protected ActionTaken(Transform target)
{
Type = '\0';
Target = target;
}
// Force implementation onto sub class
public abstract void Activate();
}
public class MovementTaken : ActionTaken
{
public int TileH { get; set; }
public int TileV { get; set; }
public MovementTaken(Transform target, int tileH, int tileV)
: base(target)
{
Type = 'M';
TileH = tileH;
TileV = tileV;
}
public override void Activate()
{
//some code using TileH and TileV
}
}
Therefore your calling code would be:
Queue<ActionTaken> actionTaken;
public void activateMovement(ActionTaken action)
{
action.Activate();
}
I'm also not sure what Type
is being used for, but if you still need it, it might be better off as a constant defined in each class that derives from ActionTaken
if you have more.
This can make sense if you end up filling your Queue<ActionTaken>
with various derived movement types. Otherwise your ActivateMovement
method could end up being a long switch
statement.
An interface also might be advantageous here:
public interface IActionTaken
{
Transform Target { get; }
void Activate();
}
Which you would then replace your queue: Queue<IActionTaken> Actions
The code for invoking all of the actions in the queue could then be extremely straightforward:
while(Actions.Count > 0)
{
IActionTaken current = Actions.Dequeue();
current.Activate();
}
Upvotes: 1
Reputation: 311428
If you know the argument passed to the method is a MovementTaken
instance, you can just downcast it:
public void activateMovement(ActionTaken toActivate)
{
MovementTaken casted = toActivate as MovementTaken;
// Do something with casted.targetTileH and/or caster.targetTileV
Upvotes: 1