禁止在Java中继承的充分理由吗?


178

禁止在Java中进行继承的充分理由是什么?例如,使用最终类或使用单个私有无参数构造函数的类?将方法定型的充分理由是什么?


1
Pedantry:如果未在代码中明确编写一个构造函数,则默认构造函数是Java编译器为您生成的构造函数。您的意思是没有参数的构造函数。
John Topley

那不是“隐式默认构造函数”吗?
cretzel

2
“您不必为类提供任何构造函数,但是在执行此操作时必须小心。编译器会自动为任何没有构造函数的类提供无参数的默认构造函数。” java.sun.com/docs/books/tutorial/java/javaOO/constructors.html –约翰·托普利
约翰·托普利

Answers:


184

此处最好的参考是Joshua Bloch的出色著作“ Effective Java”的第19项,称为“继承的设计和文档,否则将禁止继承”。(在第二版中是第17项,在第一版中是第15项。)您应该阅读它,但我将进行总结。

如果祖先不是为了继承而来的,则继承的类与其父母之间的交互可能是令人惊讶且不可预测的。

因此,类应分为两种:

  1. 设计为可扩展的类,并提供足够的文档来描述应如何完成

  2. 标记为最终课程

如果您纯粹是在编写内部代码,则可能有点过大。但是,在类文件中添加五个字符所涉及的额外工作量很小。如果您仅出于内部消耗而编写,那么将来的编码人员可以随时删除“最终”,您可以将其视为警告,指出“该类在设计时并未考虑继承”。


6
以我的经验,如果除了我之外的任何人都将使用该代码,这并不过分。我从未理解过Java为什么默认具有可重写的方法。
埃里克·韦尔瑙

9
要了解一些有效的Java,您需要了解Josh的设计理念。他说[类似]您应该始终将类接口设计为公开API。我认为多数意见是,这种方法通常过于繁琐和僵化。(YAGNI等)
Tom Hawtin-大头钉

9
好答案。(我
忍不住

36
请注意,将课程定为最终课程可能会使测试更加困难(更难进行存根或模拟)
notnoop

10
如果最后一个类正在写接口,则模拟应该不是问题。
Fred Haslam 2010年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.