Declare most complex method in base class as virtual
我一直在读Jeffrey Richter的书clr via c_,他认为在基类中定义一个方法时,如果有一个方法要声明为虚方法,并且它有一些方便的重载,那么最复杂的方法应该是虚方法,其他方法应该保留为非虚方法。他举了一个例子:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | public class Set { private Int32 m_length = 0; // This convenience overload is not virtual public Int32 Find(Object value) { return Find(value, 0, m_length); } // This convenience overload is not virtual public Int32 Find(Object value, Int32 startIndex) { return Find(value, startIndex, m_length - startIndex); } // The most feature-rich method is virtual and can be overridden public virtual Int32 Find(Object value, Int32 startIndex, Int32 endIndex) { // Actual implementation that can be overridden goes here... } // Other methods go here } |
这里的理性是什么?
答案是——干涸的原则——唯一的真理来源。有一种方法是最复杂的。B、C和D都使用其功能的子集。所以程序员是这样创建的,所有进一步的代码修改都是基于您保持A、B、C、D之间的关系的假设。如果您允许所有的B、C、D都是可重写的,那么您就打破了将其放入类中的想法。
代码可读性受到影响,人们阅读您的基类,撰写一张它如何工作的图片,然后阅读您的类,并认为他们刚刚学到的并不是您实现的情况。让团队努力工作。同样,当您5年后阅读代码时(如果需要的话)。
原因是所有更简单的方法都是通过调用虚方法实现的。如果这些是虚拟的,您可能会破坏此合同。通过只允许您更改此类的实现专门化,这些方法将遵循相同的约定。
只有一个实现,其他重载只是转发调用。使一个
我同意Jeffrey的观点;让虚拟成员成为最复杂的成员是有意义的,因为对"较小"复杂成员的调用将调用最复杂的成员,因为它们是通过方法链接调用的。此外,最复杂的成员可能是包含执行函数所需的所有参数的成员,而不包含任何外部依赖项。
如果可以的话,我稍后会详细讨论这个问题。