简体   繁体   中英

Accessing properties of a child class from list of abstract class objects

I have an Abstract class Animal, which stores some common fields, eg name, health. I have a number of animal classes eg Tiger, but I also have a class Fish which has an additional field the other animal classes don't have, canSplash .

I then have a list of Animal objects. I can access the common fields, but I cannot access the canSplash field for Fish. I am looking for help to accessing a concrete classes specific fields from an Abstract Class.

class Zoo
{
    public List<Animal> animals = new List<Animal>();

    public Zoo()
    {
        animals.Add(new Monkey());
        animals.Add(new Tiger());
        animals.Add(new Fish());
    }

    public static void displayZooPopulation()
    {
        foreach (var a in animals)
        {
            if (a.species == "fish" && a.CanSplash)
            {
                Console.WriteLine("{0} can splash",a.Name);
            }
        }
    }
}

class Fish : Animal {
    private bool canSplash
    public bool CanSplash { get; set; }
}

Simple answer would be, check the type by safely cast to it and check if it is not null :

var fish = a as Fish;
if (fish != null && fish.CanSplash)
{
    Console.WriteLine("{0} can splash",a.Name);
}

This is perfectly okay if you only have one child class which has this specific behavior. But consider you have other child classes of animals which also are able to splash, like let's say an elephant, then you have to check for the elephant's class also if you want to find all animals in your zoo which can splash.

A better approach is to use an interface for such things like ISplashable :

public interface ISplashable
{
    bool CanSplash { get; }
}

Now implement this interface in all of your child classes which should be able to splash:

public class Fish : Animal, ISplashable
{
    // ...

    public bool CanSplash { get; set; }  // this also implements CanSplash { get; }

    // ...
}

public class Elephant : Animal, ISplashable
{
    // ...

    public bool CanSplash { get { return true; } }

    // ...
}

Now you can check against that interface instead of the concrete class:

var splasher = a as ISplashable;
if (splasher != null && splasher.CanSplash)
{
    Console.WriteLine("{0} can splash",a.Name);
}

//remove the static keyword, for you can't access animals (or animals should be static)

check type of a , and take your action

The method can be:

 public   void displayZooPopulation() 
    {
        foreach (var a in animals)
        {
            if ( a is Fish)
            {
//here sure "a" is not null, no need to check against null
                var fish = a as Fish;
                //  if (a.species == "fish" && (Fish) a.CanSplash)
                if ( fish.CanSplash)
                {
                    Console.WriteLine("{0} can splash", a.Name);
                }
            }
        }
    }

BTW, you say that Animal is abstract class , where is implementation of abstract methods in Fish class :)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM