从抽象类对象列表访问子类的属性

ecc*_*esm 2 c# oop

我有一个抽象类动物,它存储一些常见的字段,例如名称、健康。我有许多动物类,例如 Tiger,但我也有一个 Fish 类,它有一个其他动物类没有的附加字段canSplash

然后我有一个 Animal 对象的列表。我可以访问公共字段,但无法访问canSplashFish的字段。我正在寻找从抽象类访问具体类特定字段的帮助。

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; }
}
Run Code Online (Sandbox Code Playgroud)

abt*_*bto 5

简单的答案是,通过安全地强制转换来检查类型并检查它是否不是null

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

如果您只有一个具有这种特定行为的子类,这完全没问题。但是考虑到您还有其他子类的动物也可以溅水,比如大象,那么如果您想在动物园中找到所有可以溅水的动物,还必须检查大象的类。

更好的方法是使用一个接口来处理这样的事情ISplashable

public interface ISplashable
{
    bool CanSplash { get; }
}
Run Code Online (Sandbox Code Playgroud)

现在在所有应该能够启动的子类中实现这个接口:

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; } }

    // ...
}
Run Code Online (Sandbox Code Playgroud)

现在您可以检查该接口而不是具体类:

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