对象继承,密封方法覆盖和C#

时间:2011-04-04 22:22:38

标签: c# oop inheritance

我有一个由另一个程序集定义的抽象类(不可编辑):

public abstract class A
{
    public void Run()
    {
        Go("Hello World");
    }

    protected virtual void Go(string message)
    {
        // Do Nothing
    }
}

现在我有一个我想从这个实现Go()的类继承的库。这里的诀窍是我不希望任何继承自我的人能够覆盖我的Go()实现,但我也不想以任何方式更改签名。我实际上希望调用这两个实现。这是我到目前为止所得到的:

public abstract class B_Intercept : A
{
    protected sealed override void Go(string message)
    {
        Console.WriteLine(message);
        Go_Impl(message);
    }

    internal abstract void Go_Impl(string message);
}

public abstract class B : B_Intercept
{
    protected new virtual void Go(string message)
    {
    }

    internal override void Go_Impl(string message)
    {
        Go(message);
    }
}

现在我的最终用户可以将他们的类继承从A切换到B而不起作用(除了我的Console.WriteLine)。

public class C : A // This can be changed to B with no other edits
{
    protected override Go(string message)
    {
        // Do stuff
    }
}

现在,原始库可以被赋予C的实例,它将被装箱为A,原始库将调用Run()。 Run将使用B_Intercept的Go(),它将消息转储到控制台,然后调用Go_Impl()。 Go_Impl将在B中运行,它将调用B的Go(),可以被C覆盖。

这感觉非常迂回。

这些方法的一些安全性还有一个额外的好处(它们不能直接调用Go_Impl),但仍有漏洞(它们可以调用base.Go)。我认为这些漏洞可以用第三层封闭,但我还没试过,坦白说我认为这有点荒谬。但它仍然感觉像很多样板代码。还有B_Intercept的蹩脚副作用需要公开而不是内部,这会以不明原因的方式提升我的图书馆的表面区域。

是否有更简单,更安全的方式?

1 个答案:

答案 0 :(得分:4)

这里的问题是你正在尝试做一些不是原始类开发人员的意图。

Go已作为virtual方法提供,现在您尝试隐藏,同时您希望将其保留为OO - (更新)并不仅如此,您还关注调用基本方法的继承类。我真诚地祝贺你的努力,关心和关注,但必须给予的东西

要么你必须使用composition来包装一个A类,并且只提供你想要提供的接口并使你的设计必须使用{ {1}}并接受它的昙花一现,主要是因为你真正改变了班级的预期行为。 对于我的两分钱,我会选择第一个选项:inheritance在一天结束时,这正是你想要实现的目标。