抽象方法和开放原理
假设我有以下设计代码:
abstract class Root
{
public abstract void PrintHierarchy();
}
class Level1 : Root
{
override public void PrintHierarchy()
{
Console.WriteLine("Level1 is a child of Root");
}
}
class Level2 : Level1
{
override public void PrintHierarchy()
{
Console.WriteLine("Level2 is a child of Level1");
base.PrintHierarchy();
}
}
如果我只看Level2
类,我可以立即看到Level2.PrintHierarchy
遵循开放/封闭原则,因为它自己做了一些事情并且它调用了基础方法,它覆盖了它。
但是,如果我只看Level1
类,它似乎违反了OCP,因为它没有调用base.PrintHierarchy
- 实际上,在C#中,编译器禁止它出现错误“无法调用抽象基类成员”。
使Level1
看起来遵循OCP的唯一方法是将Root.PrintHierarchy
改为空的虚方法,但是我不能再依赖编译器来强制派生类来实现PrintHierarchy
。
我在维护代码时遇到的真正问题是看到几十个不调用base.Whatever()
的方法。如果base.Whatever
是抽象的,那么很好,但如果不是,那么Whatever
方法可能是被拉入接口的候选者而不是具体的可覆盖方法 - 或者类或方法需要以其他方式重构,但无论哪种方式,它都清楚地表明设计不佳。
如果没有记住Root.PrintHierarchy
是抽象的或在Level1.PrintHierarchy
内置评论,我是否有其他选择来快速确定类似Level1
的类是否违反了OCP?
评论中有很多很好的讨论,也有一些很好的答案。我无法弄清楚到底要问什么。我认为让我感到沮丧的是,正如@Jon Hanna指出的那样,有时虚拟方法只是表示“你必须实现我”,而有时它意味着“你必须扩展我 - 如果你没有调用基础版本,你打破我的设计!“但是C#没有提供任何方式来表明你的意思,除了那个抽象或界面显然是一个“必须实现”的情况。 (除非Code Code中有一些东西,我认为这有点超出范围)。
但是,如果一种语言确实具有必须实现与必须扩展的装饰器,那么如果它不能被禁用,它可能会为单元测试带来巨大的问题。有这样的语言吗?这听起来很像设计合同,所以如果它在艾菲尔铁塔,我也不会感到惊讶。
最终的结果可能就像@Jordão所说的那样,而且完全是上下文的;但在我接受任何答案之前,我将暂时搁置讨论。
没有找到相关结果
已邀请:
3 个回复
舶啥戚
定义以下内容:根对象具有PrintHierarchy方法。它没有定义关于PrintHierarchy方法的更多信息。
有一个PrintHierarchy方法。它不会停止使用PrintHierarchy方法,因此它绝不违反开放/封闭原则。 现在,更重要的是:将“PrintHierarchy”重命名为“Foo”。 Level2是否遵循或违反开放/封闭原则? 答案是我们没有线索,因为我们不知道“Foo”的语义是什么。因此,我们不知道是否应该在方法体的其余部分之后,在休息之前,在其中间或根本不调用base.Foo。 应该
返回“System.ObjectSystem.ValueType1”或“1System.ValueTypeSystem.Object”来保持打开/关闭的假装,还是应该在返回“1”之前将调用分配给
到未使用的变量? 显然没有这些。它应尽可能返回有意义的字符串。它的基类型尽可能地返回有意义的字符串,并且扩展它不会受益于对其基数的调用。 打开/关闭原则意味着当我调用Foo()时,我希望发生一些Fooing,并且当我在Level1上调用它时我期望一些Level1适当的Fooing,而当我在Level2上调用它时,我期望一些Level2适当的Fooing。 Level2 Fooing是否应该涉及一些Level1 Fooing也会发生取决于Fooing是什么。
是一个帮助我们扩展课程而不是要求的工具。
仿普
爆刺疤灯