在派生 classes 中定义基础 class 构造方法

Define base class constructor methods in derived classes

我正在尝试创建一个全面的 abstract BaseClass,它定义了所有派生 classes 的创建方式,但允许派生 classes specialize/aggregate 创建过程中使用的字段和方法。这是一个简化的例子:

public abstract class BaseClass
{
    public List<String> list;

    public BaseClass()
    {
        defineList();
        optionalDoSomething();
        doSomething();
    }

    protected void defineList()
    {
        list = new List<String>();
    }

    protected void doSomething()
    {
        // do something w/ list here
    }

    protected void optionalDoSomething() {}
}

public class DerivedClass : BaseClass
{
    protected void defineList()
    {
        base.defineList();
        list.Add("something");
    }

    public DerivedClass() : base() { }
}

public class SecondDerivedClass : DerivedClass
{
    protected void defineList()
    {
        base.defineList();
        list.Add("somethingElse");
    }

    protected void optionalDoSomething()
    {
        // do something special
    }

    public SecondDerivedClass() : base() { }
}

这将使所有派生的 classes 不必重新创建相同的初始化逻辑,并且每个派生的 class 只需要 "overwrite" 中使用的必要字段和方法创建进程(可能在 class 的其他地方)。

问题:

  1. 我无法将 BaseClass' 方法标记为 virtual,因为您不能在基础构造函数中调用 virtual 方法(无论如何,我不想使用 virtual 方法,因为,例如,我不希望 DerivedClass 使用 SecondDerivedClass' defineList 方法)。

  2. 我可以将它们标记为 abstract,但那样我就无法将 "default implementations" 放入 BaseClass 并且每个派生的 class 都会有replicate/implement 这些默认值。此外,SecondDerived class 仍然需要一种方法来 "override" DerivedClass 的实现。

  3. 简单地使用new关键字"hide" less derived class'方法是行不通的。

获得这个图案的正确方法是什么?

TLDR:根据我在下面的评论: 如果 BaseClass 是使用方法 Aabstract class,并且 DerivedClass 是从 BaseClass 派生的 class(不一定是BaseClass 的直接子代),然后在 BaseClass 中调用 A' 构造函数应该在继承层次结构中的每个 class 中调用 A(),直到并包括 DerivedClass(但没有进一步)。我们可以假设 A(强制)定义在每个中间 class 上。

实现您想要的方法的一种方法是向基 class 添加显式 Initialize 方法并在那里执行初始化逻辑,例如:

public abstract class BaseClass
{
    public List<String> list;

    public BaseClass()
    {

    }

    public void Initialize()
    {
        defineList();
        optionalDoSomething();
        doSomething();
    }
}

试试这个解决方案,实现是用受保护的虚拟方法实现的,所以它从外部不可见,在派生中也不需要 类:

    public abstract class BaseClass
    {
        public List<String> List { get; protected set; }

        protected BaseClass()
        {
            defineList();
            optionalDoSomething();
            doSomething();
        }

        protected void defineList()
        {
            // default implementation here
            List = new List<String>();

            internalDefineList();
        }

        protected void doSomething()
        {
            // default implementation here
            internalDoSomething();
        }

        protected void optionalDoSomething()
        {
            // default implementation here
            internalOptionalSomething();
        }

        protected virtual void internalDefineList()
        {
        }

        protected virtual void internalDoSomething()
        {
        }

        protected virtual void internalOptionalSomething()
        {
        }
    }

    public class DerivedClass : BaseClass
    {
        protected override void internalDefineList()
        {
            var list = List;
        }

        protected override void internalDoSomething()
        {
        }

        // this method is not required
        /*          
        protected override void internalOptionalSomething()
        {
        }
        */
    }

我认为你应该参考template-method-design-pattern

Define the skeleton of an algorithm in an operation, deferring some steps to subclasses. Template Method lets subclasses redefine certain steps of an algorithm without changing the algorithm's structure.

你可以尝试类似的东西

abstract class AbstractClass
  {
    public List<String> list;
    public abstract void PrimitiveOperation1();

    public void TemplateMethod()
    {
      //initialize code that each class should perform
      PrimitiveOperation1();
    }
  }

class DerivedClass: AbstractClass
  {
    public override void PrimitiveOperation1()
    {
      list.Add("something");
    }
  }

用法

AbstractClass abstractClass1 = new DerivedClass();
abstractClass1.TemplateMethod();