C#具有使用子类变量的父类方法

时间:2018-11-08 22:34:47

标签: c# oop inheritance

我一直面临挑战,质疑我对OOP的信念。请让我知道这怎么可能:

我有一个带有静态列表的父类(用于跟踪创建的所有对象,主要是出于UI DataGrid的原因),还有一个引用该列表的Method。像这样

abstract class Animal
{
    public static List<Animal> objList;
    public String Name;

    public Animal(String Name)
    {
        this.Name = Name;
        objList.Add(this);
    }

    public virtual void delete(int i)
    {
        objList.RemoveAt(i);
    }

现在我有一个带有静态列表的子类(相同名称,只是不同的类),但是为了使该方法引用child.list,我必须重写该方法。这样

class Cat : Animal
{
    public static List<Cat> objList;

    public Cat(String Name) : base(Name)
    {

    }

    //whould it be possible to ommit this method?
    public override void delete(int i)
    {
        objList.RemoveAt(i);
    }
}

这不是最好的方法。如果我有5个孩子,他们将粘贴同一部分代码副本。 父类“删除”方法必须有一种方法,如果从子对象中调用该方法,则会从子列表中删除,而不是从父列表中删除。

2 个答案:

答案 0 :(得分:0)

尽管静态属性和方法可能会被遮盖,但它们不适合以OOP方式覆盖。

public class Parent : IDisposable
{
    private static List<Parent> objList = new List<Parent>();
    private static IReadOnlyList<Parent> readOnlyList = new ReadOnlyCollection<Parent>(objList);
    public static IEnumerable<Parent> Instances { get { return readOnlyList; } }

    private bool _isDisposed = false;
    public bool IsDisposed {  get { return _isDisposed;  } }

    public Parent()
    {
        objList.Add(this);
    }

    public void Dispose()
    {
        OnDispose(true);
        GC.SuppressFinalize(this);
    }

    protected virtual void OnDispose(bool disposing)
    {
        if(disposing) { objList.Remove(this); }
        _isDisposed = true;
    }
}

public class Child : Parent
{
    private static IEnumerable<Child> _instances = Parent.Instances.OfType<Child>();
    public new static IEnumerable<Child> Instances { get { return _instances; }}

    public Child() : base()
    {

    }
}

现在,如果要从列表中删除第i个项目,只需使用 Parent.Instances(i).Dispose();

您还可以通过执行 Child.Instances(i).Dispose()

来删除第i个Child实例。

编辑:终结器已从“父级”中删除,如以下注释中所述。

Edit2 :按照注释中的建议,将Child类中的LINQ表达式简化为使用.OfType()。

答案 1 :(得分:-1)

该集合不属于基类,当然,它也不属于任何派生类。

不幸的是,您没有展示List<Animal>的用法,因此很难在不推断您可能不希望的行为的情况下显示有意义的答案。

但是,如果您坚持要这样做,则只需要拥有一个集合即可容纳所有动物,并声明一个静态属性,该属性可以根据每个子类中的类型过滤原始集合。

public abstract class Animal
{
    // this is the _only_ field that should contain
    // a list of all the animals.
    protected static readonly List<Animal> animals = new List<Animal>();

    // Expose a read-only wrapper as public
    public static IReadOnlyList<Animal> AllAnimals => animals.AsReadOnly();

    protected Animal(string color)
    {
        animals.Add(this);
        this.Color = color;
    }
    public string Color { get; }

    public void RemoveMe()
    {
        int index = animals.IndexOf(this);
        if (index >= 0)
        {
            animals.RemoveAt(index);
        }
    }
}    

public class Cat : Animal
{
    public static IReadOnlyList<Cat> AllCats => animals.OfType<Cat>().ToList().AsReadOnly();
    public Cat(string name, string color) : base(color)
    {
        this.Name = name;
    }
    public string Name { get; }
}

public class Fish : Animal
{
    public static IReadOnlyList<Fish> AllFish => animals.OfType<Fish>().ToList().AsReadOnly();
    public Fish(string color) : base(color)
    {
    }
}

static class Program
{
    static void Main(string[] args)
    {
        var cat1 = new Cat("Whiskers", "Tabby");
        var fish1 = new Fish("Striped");
        var cat2 = new Cat("Snoflake", "White");
        var cat3 = new Cat("Midnight", "Black");

        cat2.RemoveMe();

        // list all remaining cats below
        foreach (var cat in Cat.AllCats)
        {
            Debug.WriteLine($"{cat.Name} is a {cat.Color} cat.");
        }
        // Result in Output:
        //Whiskers is a Tabby cat.
        //Midnight is a Black cat.

    }
}