继承会破坏封装吗?

时间:2012-06-27 01:01:26

标签: java inheritance encapsulation

假设我有一个CSV文件,我创建了一个名为CsvFile的类,它从java.io.File扩展而来。此类可以解析CSV文件并返回一些数据,例如文件中有多少列。它也可以用于以java.io.File为输入的函数。像F ileUtils.copyFile(File from, File to)

我的同事认为我从继承中暴露了太多。他的想法是将java.io.File包装在私有属性中,而不是继承它。他认为从文件中断封装中暴露所有公共方法/属性,但我认为它是一个好处,因为我们免费获得java.io.File中的所有函数。

您怎么看?

7 个答案:

答案 0 :(得分:15)

我宁愿同意您的同事:继承java.util.File会泄露不适用于CsvFile个对象的方法,例如list()listFiles(),{{1}等等。

setExecutable()置于getter后面的属性听起来是一个更好的选择:它不会向您的类的用户显示不相关的操作,并允许您从您选择的基类继承。

答案 1 :(得分:5)

我认为这一切都取决于班级的目的。如果你真的想扩展行为,那么我会说这是有道理的。如果您没有扩展File的行为但只是制作CSV对象,那么封装会将其行为限制为仅仅意图。

答案 2 :(得分:1)

您也可以考虑使其更通用,以便它可以接受来自各种来源的CSV格式的InputStream或Reader,这些来源不能(或​​不能轻易地)发送到文件系统。为方便起见,您仍然可以使用java.io.File setter / constructor。

答案 3 :(得分:1)

这实际上是一场激烈的辩论。你的同事在这个问题上处于历史的右侧。一般来说,继承问题归结为is-a与has-a的关系。通常,使用组合比继承更灵活。在你的情况下,它是一个近距离通话毕竟csv文件是一个文件。说csvfile有一个文件甚至听起来不对。还可以考虑进行继承,而不是包装继承的文件,以便只公开您想要的那些CSV文件方法。我还会研究一下你想从A继承的一些设计模式,但是向世界展示一个更有限的界面。我几乎可以肯定这有一个设计模式。只是不记得名字....

“或者我想不到,但结合两者就是这样。第一次继承使车轮不再重新发明,而不是封装的图案,以便车轮达到目的。”

答案 4 :(得分:0)

也许我的观点过于宽松但...... 封装和继承是有原因的。 (观察从汇编语言到高级语言的“演变”。)原因是程序员。使用更高级别的抽象/范例,您可以编写更好的代码。诀窍在于定义“更好”。对我来说,这是可维护性,自我文档和代码重用。这就是为什么我会在你的特定情况下选择封装而不是继承。编写一次可能需要更多的工作,但是将来更容易维护。 (当然,假设这个CSV内容是更大项目的一部分。)

答案 5 :(得分:0)

您的同事提到的方法还有一个好处,即只需暴露您真正需要的方法,您的API就会变得非常小 - 这样可以明确告诉用户如何使用您的类(您可以将公共API视为某种类型)文件)。

答案 6 :(得分:0)

关于你的问题

  

继承会破坏封装吗?

然后,根据Joshua Bloch的Effective Java,继承总是打破封装:

  

与方法调用不同,继承违反了封装   [Snyder86]。换句话说,子类取决于实现   其超类的正确功能的细节。

关于您是否应该使用继承或组合,正如许多人已经说过的那样,这取决于您的CsvFile是一个文件,在java.util.File的意义上。