Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C# Polymorphism - Accessing Properties of child class that aren't in the parent

I'm running into issues with being able to call functions/properties that are unique to the child class. I'm wondering if there is a way to do do something similar to the following:

public class Creature
{
   public int HealthPoints {get; set;}
   public string Name {get; set;}
   public int AttackValue {get; set;}

   public Creature();
}

public class Magical : Creature
{
   public int Mana {get; set;}
}

So, in this rudimentary example, I'd have a list of Creatures and would need to be able to call from that the Mana property of any given Magical creature.

like image 631
DivinusVox Avatar asked Jan 31 '11 18:01

DivinusVox


3 Answers

The short answer:

As you have surely seen in other answers, you can access the Mana property of magical creatures as follows:

foreach (Creature creature in creatures)
{
    if (creature is Magical magical)
    {
        // ... do something with 'magical.Mana' here...
    }
}

Going a step further:

Since we're talking about polymorphism already, you should know that if (x is SomeType) { .. } can be a code smell. Let's say you indeed have a foreach loop for processing all your creatures. It might then be better to create a virtual method in the base class, and do whatever you're doing inside the foreach loop in that virtual method. You would then override the method in your Magical class and thereby get rid of the if statement.

Let's do an example. Let's say, all your creatures get hit and lose some energy. Normal creatures lose health points, while magical creatures lose mana:

public partial class Creature   // rest of your class is omitted in this example
{
    public virtual void TakeHit()
    {
        // whatever you had in your original foreach loop, e.g.:
        HealthPoints--;
    }
}

public partial class Magical : Creature
{
    public override void TakeHit()
    {
        // ... any special processing for Magical creatures goes here, e.g.:
        Mana--;
        // (you could also call 'base.TakeHit()' in this method.)
    }
}

Your original foreach loop now becomes much simpler:

foreach (Creature creature in creatures)
{                        // note: no more if statement -- The virtual method
    creature.TakeHit();  // invocation now takes care of distinguising
}                        // different (sub-)types of Creatures!

I would like to recommend a very nice presentation on this very topic to you: Conditionals and Polymorphism.

like image 85
stakx - no longer contributing Avatar answered Nov 07 '22 02:11

stakx - no longer contributing


So, in this rudimentary example, I'd have a list of Creatures and would need to be able to call from that the Mana property of any given Magical creature.

Yes, this is possible. Use Enumerable.OfType<T>:

IEnumerable<Creature> creatures = new List<Creature>();
// populate creatures
var magicalCreatures = creatures.OfType<Magical>();
foreach(var magicalCreature in magicalCreatures) {
    Console.WriteLine(magicalCreature.Mana);
}
like image 11
jason Avatar answered Nov 07 '22 02:11

jason


You need to do a conversion to "Magical" at that point. For example:

Creature aCreature = GetMyCreature();
Magical asMagical = aCreature as Magical; // Using "as" operator..
if (asMagical != null)
    Console.WriteLine(asMagical.Mana);
like image 5
Reed Copsey Avatar answered Nov 07 '22 04:11

Reed Copsey