【问题标题】:C# Make a List to hold any derived children of a base classC# 创建一个列表来保存基类的任何派生子类
【发布时间】:2013-04-16 20:42:32
【问题描述】:

所以我希望设置一个抽象基类来派生子类。所有的工作都将在孩子们身上进行,但我希望孩子们能够相互参考。

这是一些伪代码:

public abstract class BaseClass<T> : SomeOtherClass {

    public List<BaseClass> listOfChildren;

    protected T thisChild;

    public void DoMoreStuff(){
        Debug.Log("Doing more stuff");
    }

    protected virtual void DoSomething(int i){
        listOfChildren[i].DoMoreStuff();
    }
}

public class FirstChildClass : BaseClass<FirstChildClass> {

    FirstChildClass<T>(){
        thisChild = this;
    }

    public void FirstClassStuff(){
        Debug.Log("first class stuff");
    }

}
public class SecondChildClass : BaseClass<SecondChildClass> {

    public void SecondClassStuff(){
        Debug.Log("second class stuff");
    }
}

我如何制作一个通用列表来接受任何子类?

我是否需要使用 T 对 listOfChildren 进行类型转换才能使用 DoMoreStuff()?

就其本身而言,此设置是否存在其他固有问题?

【问题讨论】:

    标签: c# inheritance


    【解决方案1】:

    我认为您的解决方案过于复杂。如果您不想在每个节点中存储任何数据 - 尝试在没有泛型的情况下解决这个问题。我将为您提供所需行为的简单直接的实现作为起点。

    public abstract class BaseClass  {
    
        private IList<BaseClass> children = new List<BaseClass>();
    
        public void AddChild(BaseClass child)
        {
            this.children.Add(child);
        }
    
        protected virtual void DoMoreStuff(){
            Debug.Write("Doing more stuff");
        }
    
        public void DoSomething(int i){
            children[i].DoMoreStuff();
        }
    }
    
    public class FirstChildClass : BaseClass {
    
        protected override void DoMoreStuff(){
            Debug.Write("first class more stuff");
        }
    
    }
    
    public class SecondChildClass : BaseClass {
    
        protected override void DoMoreStuff(){
            Debug.Write("second class more stuff");
        }
    }
    

    现在可以

    var root = new FirstChildClass();
    
    root.AddChild(new FirstChildClass());
    root.AddChild(new SecondChildClass());
    root.AddChild(new FirstChildClass());
    
    root.DoSomething(1); //will print second class more stuff
    root.DoSomething(0); //will print first class more stuff
    

    【讨论】:

    • 更进一步,我可以轻松地将每个子类设为 Singleton 吗?
    • @user1297102 你真的需要那个吗?
    • 这在某些情况下会很有用,是不是有点困难?我在想我可以在基础中放置一个“受保护的静态 T 实例”(但这需要 BaseClass 仪式?),不确定如何将构造函数设置为 if(!instance)instance=this;else"already存在”反对这一点。
    • 静态和继承不能混用
    【解决方案2】:

    您需要区分子和子数据。子类简单地从其父类继承,为数据提供更详细的结构(例如AnimalDog)。另一方面,子数据意味着数据表示的任何内容都相互关联(例如ReceiptReceiptLineItem)。

    通常,两者不会重叠。 Receipt 类看起来与ReceiptLineItem 类完全不同,ReceiptExternalPurchaseOrder 彼此无关,尽管它们都从Purchase 继承了它们的结构。当它们重叠时,你就有了一个树结构。一个Product 可能由更多Products 组成,每个Products 又可能由更多Products 组成。


    假设您正在寻找第一种继承类型(类结构),我将重写您的代码:

    public abstract class BaseClass : SomeOtherClass {
    
        public static List<BaseClass> listOfChildren = new List<BaseClass>();
    
        public void DoMoreStuff(){
            Debug.Log("Doing more stuff");
        }
    
        protected virtual void DoSomething(int i){
            listOfChildren[i].DoMoreStuff();
        }
    }
    
    public class FirstChildClass : BaseClass {
    
        FirstChildClass(){
           // Set some things unique to this class
        }
    
        public void FirstClassStuff(){
            Debug.Log("first class stuff");
        }
    
    }
    public class SecondChildClass : BaseClass<SecondChildClass> {
    
        public void SecondClassStuff(){
            Debug.Log("second class stuff");
        }
    }
    

    然后您可以使用BaseClass.listOfChildren 访问主列表。如果您希望所有孩子自动注册自己,您可以将其添加到 BaseClass 构造函数中:

    protected BaseClass()
    {
       listOfChildren.Add(this);
    }
    

    【讨论】:

    • 更进一步,我可以轻松地将每个子类设为 Singleton 吗?
    • 只是出于对技术的好奇,如果我想实现我不那么出色的设计,如何才能使该列表工作? (如果将来我需要混合泛型和类)
    • @user1297102 - 我不太清楚你的意思。如果您问如何拥有List&lt;BaseClass&gt;,那么您实际上需要一个BaseClass 类(或接口),BaseClass&lt;T&gt; 可以继承(或实现)它。 BaseClass&lt;T&gt; 的存在并不意味着非泛型形式的存在,每个不同的T 都会产生不同的类,因此如果只有泛型类型,就无法将它们“分组”。
    • 谢谢,我就是这么想的,但不确定我是不是没有想到什么。
    猜你喜欢
    • 2015-07-23
    • 1970-01-01
    • 2018-05-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多