我有一个由另一个程序集定义的抽象类(不可编辑):
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的蹩脚副作用需要公开而不是内部,这会以不明原因的方式提升我的图书馆的表面区域。
是否有更简单,更安全的方式?
答案 0 :(得分:4)
这里的问题是你正在尝试做一些不是原始类开发人员的意图。
Go
已作为virtual
方法提供,现在您尝试隐藏,同时您希望将其保留为OO - (更新)并不仅如此,您还关注调用基本方法的继承类。我真诚地祝贺你的努力,关心和关注,但必须给予的东西。
要么你必须使用composition
来包装一个A类,并且只提供你想要提供的接口并使你的设计或必须使用{ {1}}并接受它的昙花一现,主要是因为你真正改变了班级的预期行为。 对于我的两分钱,我会选择第一个选项:inheritance
。在一天结束时,这正是你想要实现的目标。