13

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

我的同事认为我从继承中暴露了太多。他的想法是java.io.File通过将其保存在私有财产中来包装,而不是继承它。他认为从文件中断封装中公开所有公共方法/属性,但我认为这是一个好处,因为我们可以java.io.File免费获得所有功能。

你怎么看?

4

7 回答 7

15

我宁愿同意你同事的观点:继承java.util.File会暴露不适用于CsvFile对象的方法,例如list(), listFiles(),setExecutable()等。

在getterjava.util.File后面创建一个属性听起来是一个更好的选择:它不会向您的类的用户透露不相关的操作,并允许您从您选择的基类继承。

于 2012-06-27T01:12:00.750 回答
5

我认为这完全取决于课程的目的。如果你真的想扩展这种行为,那么我会说这是有道理的。如果您没有扩展 File 的行为,而只是制作一个 CSV 对象,那么封装会将其行为限制在其意图的范围内。

于 2012-06-27T01:12:47.020 回答
1

这实际上是一场大辩论。你的同事在这件事上站在历史的正确一边。一般来说,继承问题归结为 is-a 与 has-a 的关系。一般来说,使用组合比使用继承更灵活。在你的情况下,这是一个近距离的电话。毕竟一个csv文件是一个文件。说 csvfile has-a file 甚至听起来都不对。也可以考虑进行继承,而不是包装继承的文件,以便仅公开您想要的那些 CSV 文件方法。我还将研究一些您希望从 A 继承但向世界公开更有限接口的设计模式。我几乎可以肯定有一个设计模式。就是想不起来名字了。。。。

“要么,要么我认为不是,但将两者结合起来是一种方式。首先继承是为了不重新发明轮子,而不是封装模式,以便轮子服务于它的目的。”

于 2012-06-27T01:18:34.880 回答
1

您还可以考虑使其更通用,以便它可以接受来自无法(或不容易)发送到文件系统的各种来源的 CSV 格式的 InputStream 或 Reader。为方便起见,您仍然可以使用 java.io.File 设置器/构造器。

于 2012-06-27T01:17:41.223 回答
0

至于你的问题

继承会破坏封装吗?

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

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

关于你应该使用继承还是组合,正如许多人已经说过的,这取决于你的CsvFileis-a 文件,在java.util.File.

于 2015-01-05T12:14:04.140 回答
0

您的同事提到的方法还有一个好处,即您的 API 变得非常小,只需公开您真正需要的方法 - 这使用户清楚如何使用您的类(您可以将公共 API 视为某种文档) .

于 2012-06-27T08:38:50.560 回答
0

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

于 2012-06-27T01:28:01.147 回答