重写嵌套的类函数还是使用委托?

本文关键字:嵌套 类函数 重写 | 更新日期: 2023-09-27 17:52:38

我有一个base class,里面有一个嵌套类型。外层(基本)类型中有一个函数,稍后将被它的子类型覆盖。事实上,从OO的角度来看,这个函数属于inner type,但我仍然需要它,被base classsubtypes覆盖。

我应该使用这个函数作为inner typecallback,还是只是把它移动到inner type里面,让我们的subtypes从那里重写它?

EDIT:添加示例代码

class A
{
    protected void func() { /* do something */ }
    class B { /**/ }
}
// OR
class A
{
    class B
    {
        protected void func() { /* do something */ }
    }
}
// Then
class C : A
{
    override func() { /**/ }
}

重写嵌套的类函数还是使用委托?

我的建议是为内部类型函数创建一个委托,该函数由基类的构造函数初始化:

internal class BaseClass
{
    public BaseClass(Action myAction)
    {
        this.innerType = new InnerType(myAction);
    }
    public BaseClass()
    {
        // When no function delegate is supplied, InnerType should default to
        // using its own implementation of the specific function
        this.innerType = new InnerType();
    }
}

如您所见,派生类型可以使用:base (overridenAction)调用基构造函数,在那里它们可以提供自己对最内层类型的函数实现。当然,你没有义务使用Action,但任何你想要的委托。

在我看来,你所描述的看起来像是战略设计模式。考虑使用这种模式。您的代码将更易于维护,因为它包含了易于识别的模式。你也可以看看状态设计模式,通常你必须在这两者之间做出选择,它们是紧密相连的。

在这个场景中:

class A
{
    class B
    {
        protected void func() { // do something }
    }
}

不能从A类派生并在B类中重写func()

从你的描述看来,a派生类应该能够在内部类B中覆盖一些函数(或功能),这表明你可能应该重新考虑你的设计。要么提取B,不让它成为一个内部类,要么让你想要的功能通过这样的接口覆盖显式依赖:

class A
{
    private B _MyB;
    public A(ISomeBehaviour behaviour)
    {
        _MyB = new B(behaviour);
    }
}

无论如何,如果你想坚持你的设计,那么我不建议使用委托方法,而是选择重写,因为使用委托,如果在子类中只需要添加装饰,则更难添加。

这就是外部类如何作为内部服务类的策略。

注意,不建议使用TemplateMethodStrategy这样的模式名作为真正的类名,使用在域中有意义的名称。同样适用于OuterInner

public class Consumer
{
    public void Foo()
    {
        IOuterFoo fooService = new Derived();
        fooService.OuterFoo();
    }
}
// ...
public interface IOuterFoo
{
    void OuterFoo();
}
abstract class Base : Base.IStrategy, IOuterFoo
{
    public void OuterFoo() { _service.Foo(); }
    private readonly InnerService _service;
    protected Base() { _service = new InnerService(this); }
    private interface IStrategy { void Foo(); }
    private class InnerService
    {
        private readonly IStrategy _strategy;
        public InnerService(IStrategy strategy) { _strategy = strategy; }
        public void Foo() { _strategy.Foo(); }
    }
    void IStrategy.Foo() { TemplateMethodFoo(); }
    protected abstract void TemplateMethodFoo();
}
class Derived : Base
{
    protected override void TemplateMethodFoo()
    {
        throw new NotImplementedException();
    }
}