【问题标题】:Call the same overridden method one after another in multiple classes在多个类中依次调用相同的重写方法
【发布时间】:2019-07-01 05:48:54
【问题描述】:

我有一个基类C1,它提供了几个方法的默认实现,如C2 和许多自定义实现Cx (+20),如下所示:

abstract class C1
{
    public abstract void M1();
}

abstract class C2 : C1
{
    // other overridden members ...

    // M1(); has no default implementation yet.
}

class Cx : C2
{
    public override void M1()
    {
        // ...
    }
}

现在,我想链接C2.M1Cx.M1,因为我需要添加一个新的通用功能。通常我会创建一个新的抽象方法并由第二个 base 类调用它,如下所示:

abstract class C1
{
    public abstract void M1();
}

abstract class C2 : C1
{   
    // M1 should get a default implementation 
    // and then M1 in the next derived class should be called
    public override void M1()
    {
        // ...
        M1Internal();
    }

    protected abstract void M1Internal();
}

class Cx : C2
{
    protected override void M1Internal()
    {
        // ...
    }
}

但是,我有 20 多个这样的类,并且全部更新它们需要大量工作,所以我想知道是否有另一种方法可以让我在 C2Cx 中覆盖 M1 并调用它们按此顺序 C1.M1() 然后 Cx.M1() 而不创建新的 intermediate 辅助方法。这种情况有没有更好的模式?

【问题讨论】:

  • C1C2Cx 类有什么关系?谁继承谁?
  • @MindSwipe 哎呀,对不起,我忘了添加继承。固定!
  • @John 我可以,但这意味着将相同的代码添加到所有其他类。我宁愿避免这种情况,因为它很容易忘记。
  • C2 中的// Other overriden members... 是什么意思? M1 是否在 C2 中实现?
  • @MindSwipe 我更新了代码。不,M1 目前没有默认实现,但它应该有一个。然后应该调用下一个M1

标签: c# inheritance


【解决方案1】:

我认为在这种情况下最好使用装饰器模式。尽可能使用组合而不是继承。

abstract class C1
{
    public abstract void M1();
}

class Cx : C1
{
    public override void M1()
    {
        // ...
    }
}

class CxWithCommonBehavior : C1
{
    C1 realObject;

    public CxWithCommonBehavior(C1 realObject)
    {
        this.realObject = realObject;
    }

    public override void M1()
    {
        // common behavior
        realObject.M1();
    }
}

请注意,对于所有派生的 Cx 类,您只需要一个 CxWithCommonBehavior 类 - 您在构造函数中传递修饰的实例。

这样您可以添加更多行为,以所有可能的方式将它们链接起来,甚至在运行时添加或删除它们

【讨论】:

  • 我需要稍微调整架构,但我认为这实际上可能是最适合未来的设计。
  • 酷!我已经检查了这将如何与 Autofac 一起使用,它本身就支持这一点,所以我也可以自动组合所有这些新的组合 ;-)
  • 如果其他人正在寻找它:decorators with Autofac
【解决方案2】:

直接在Cx.M1 上拨打base.M1 怎么样?

class Cx : C2
{
    protected override void M1()
    {
        base.M1();//i.e. C2.M1()
        //Cx.M1 internal logic
    }
}

【讨论】:

  • 这很容易忘记和自动化。尤其是在新课程中,但在较小的解决方案中绝对是一种选择。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-05-07
  • 1970-01-01
  • 2011-12-26
相关资源
最近更新 更多