Reputation: 55
I'm creating a game in order to learn C# programming.
I have a class called Unit
and two derived types, Wolf
and Spider
.
I've also created a class called UnitList
that contains a List<Unit>
where I would like to store my Unit
instances.
There is also another class called Battle
where a method loops through each Unit
in my List<Unit>
. I would like to use a different method based on the Type
of Unit
, be it a Wolf
or a Spider
.
Please see the image below as I am not good at explaining concepts; I have been stuck on this for days.
Upvotes: 0
Views: 70
Reputation: 1800
What you are probably looking for is the c# is
operator.
For example
if(unit is Wolf)
{
// Do something
}
else if (unit is Spider)
{
// Do Something
}
Once you are in those blocks, you can use a type cast to call your methods.
if(unit is Wolf)
{
((Wolf)unit).WolfAttack();
}
However, there is a much cleaner way of doing this in C# using the inheritance tree you have already set up.
class Unit
{
public virtual void Attack()
{
Console.WriteLine("Unit attacks!");
}
}
class Wolf : Unit
{
public override void Attack()
{
Console.WriteLine("Wolf attacks!");
}
}
class Spider : Unit
{
public override void Attack()
{
Console.WriteLine("Spider attacks!");
}
}
By marking the method on Unit
as virtual
you can override its behavior on classes that inherit from Unit
. Thus your code to call the attack now just becomes
foreach(Unit unit in team1.GetList())
{
unit.Attack();
}
as it will call the proper Attack()
function for each Unit
be it a Spider
or a Wolf
.
There is also an alternative to this, and that is to use Interfaces. If there is no shared implementation between the Spider
and Wolf
class, this is often a good way to go rather than using abstract
classes.
You would define an IUnit
interface, for example
public IUnit
{
int Health { get; set; }
void Attack();
}
Then instead of inheriting from Unit
you would implement IUnit
instead.
class Wolf : IUnit
{
public int Health { get; set; }
public void Attack()
{
Console.WriteLine("Wolf attacks!");
}
}
class Spider : IUnit
{
public int Health { get; set; }
public void Attack()
{
Console.WriteLine("Spider attacks!");
}
}
You would then use IUnit
in place of Unit
.
Both methods are valid, and both have advantages and disadvantages. Classes are allowed to implement many interfaces, but only inherit one class. Interfaces can not define functionality, so they can't completely replace inheritance. There are more, but that is the most basic difference between the two.
Upvotes: 1
Reputation: 60
You're trying to compare a System.Type
with an instance
. What you're looking to do is use the typeof
operator or the is/as
construct for C#. Rather, for a better solution, you could use inheritance.
You're Unit class could be declared abstract as such:
abstract class Unit
{
private int health;
private int damage;
protected Unit()
{
health = 100;
}
public abstract void Attack();
}
While your Wolf class could be:
class Wolf : Unit
{
public override void Attack()
{
// Do Something...
}
}
And you could then retrieve each Unit
instance from your list and call Unit.Attack();
and it would call the respective Attack()
.
Upvotes: 1