Home > Mobile >  C# acces property from abstract classes
C# acces property from abstract classes

Time:03-16

I have a class structure like this:

BaseAnimal.cs:

public abstract class BaseAnimal
{
   public string? Species { get; set; }
   public double Price { get; set; }
}

Then I have this two classes:

public abstract class Carnivore : BaseAnimal
{
    public double MeatFood { get; set; }
}

public abstract class Herbivore : BaseAnimal
{
   public double GreenFood { get; set; }
}

And then I have the sub classes:

public class Ape : Herbivore
{
    public Ape()
    {
        Species = "Ape";
        GreenFood = 10.0;
        Price = 10000.0;
    }
}

Then I have a facotry which is already working with this line to get all the attributes from an animal:

public BaseAnimal[] Animals = prototypes.Values.ToArray();

And in my Main class I would like to read the properties of the Animals:

 private void cboAnimals_SelectionChanged(object sender, SelectionChangedEventArgs e)
 {
    Debug.WriteLine(animalFactory.Animals[0].);
 }

The problem with this code is, that I cannot access the properties specified in the Herbivore.cs and Carnivore.cs

CodePudding user response:

Simplest is probably to check the type:

var foodAmount = animalFactory.Animals[0] switch {
     Carnivore c => c.MeatFood ,
    Herbivore h => h.GreenFood ,
    _ => throw new InvalidOperationException()
};

But this is a typical example of inheritance taught in introductory programming. As a general rule, if you need to check the type, you might not have thought thru your type system well enough. The idea with inheritance is that everything implementation specific should be delegated to the implementation, so the user of the object do not need to know the concrete type.

I have some difficulty providing concrete recommendations since the example is so artificial, But I would recommend reading Eric Lippert series on Wizards and Warriors for a nice introduction to inheritance, and how people often do it wrong.

CodePudding user response:

The problem is that animals array is of type BaseAnimal. You'll need to unbox it (ie cast it to it's subtype), you'll need some logic to check the type also, so something like

if (obj is Herbivore) 
{
   var herb = (Herbivore)obj;
   herb.Greenfood= 123m;
}

It seems messy but at some point you need to get the concrete type.

CodePudding user response:

Animals is an array of BaseAnimal. This class doesn't have a MeatFood or a GreenFood property. That's why you can't access these properties. If you could access them, this code would be possible:

BaseAnimal animal = new Ape();
Console.WriteLine(animal.MeatFood);

But Ape has no MeatFood property. If you want to access these properties, you have know whether your Animals[0] is a Carnivore or a Herbivore:

private void cboAnimals_SelectionChanged(object sender, SelectionChangedEventArgs e)
 {
    if(animalFactory.Animals[0] is Carnivore carnivore)
    {
        Debug.WriteLine(carnivore.MeatFood);
    }
    else if (animalFactory.Animals[0] is Herbivore herbivore)
    {
        Debug.WriteLine(herbivore.GreenFood);
    }
 }

But maybe you realize at this point that you won't get good code by this. This is a sign that your class structure is not the best. In fact, why do you have to properties MeatFood and GreenFood? What is the difference between them? Both a of a double type. Hence maybe you should have a Food property in your BaseAnimal class and distinguish the type of food by an enum:

public enum FoodType
{
   Meat,
   Green
}

public abstract class BaseAnimal
{
   public string? Species { get; set; }
   public double Price { get; set; }
   public double Food { get; set;}
   public abstract FoodType FoodType {get;}
}

public abstract class Carnivore : BaseAnimal
{
    public override FoodType FoodType{ get { return FoodType.Meat; } }
}

public abstract class Herbivore : BaseAnimal
{
   public override FoodType FoodType{ get { return FoodType.Green; } }
}
  • Related