开闭原理和Java“最终”修饰符
开放封闭原则指出,“软件实体(类,模块,函数等)应该开放扩展,但封闭修改”。
然而,Joshua Bloch在他的名著“Effective Java”中给出了以下建议:“设计和记录继承,否则禁止继承”,并鼓励程序员使用“final”修饰符来禁止子类化。
我认为这两个原则显然是相互矛盾的(我错了吗?您在编写代码时遵循哪个原则,为什么?你是保持类的开放状态,不允许继承其中一些(哪些?),还是尽可能使用最终修饰符?
开放封闭原则指出,“软件实体(类,模块,函数等)应该开放扩展,但封闭修改”。
然而,Joshua Bloch在他的名著“Effective Java”中给出了以下建议:“设计和记录继承,否则禁止继承”,并鼓励程序员使用“final”修饰符来禁止子类化。
我认为这两个原则显然是相互矛盾的(我错了吗?您在编写代码时遵循哪个原则,为什么?你是保持类的开放状态,不允许继承其中一些(哪些?),还是尽可能使用最终修饰符?
坦率地说,我认为开放/封闭原则与其说是不合时宜的,不如说是不合时宜的。它起源于80年代和90年代,当时OO框架建立在一切必须从其他东西继承的原则之上,一切都应该是可亚类化的。
这在MFC和Java Swing等时代的UI框架中最为典型。在Swing中,你有荒谬的继承,其中(iirc)按钮扩展复选框(或相反的方式)给出了其中一个未使用的行为(我认为这是设置Disabled()调用复选框)。为什么他们有共同的祖先?除了,嗯,他们有一些共同的方法之外,没有其他原因。
如今,构图比继承更受青睐。虽然Java默认允许继承,但.Net采取了(更现代的)方法,默认情况下不允许继承,我认为这更正确(并且更符合Josh Bloch的原则)。
DI/IoC也进一步说明了组成。
Josh Bloch还指出,继承会破坏封装,并给出了一些很好的例子来说明原因。还已经证明,如果通过委派而不是扩展类来更改 Java 集合的行为,则更改 Java 集合的行为会更加一致。
就我个人而言,我在很大程度上认为继承只不过是一个隐含的细节。
我不认为这两种说法相互矛盾。类型可以打开以进行扩展,但仍可关闭以进行继承。
一种方法是使用依赖注入。类型可以在创建时提供这些实例,而不是创建自己的帮助程序类型的实例。这允许您更改类型的部分(即打开以进行扩展),而无需更改类型本身(即关闭以进行修改)。