禁止在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.