Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/393.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/design-patterns/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 重组合轻继承_Java_Design Patterns_Inheritance - Fatal编程技术网

Java 重组合轻继承

Java 重组合轻继承,java,design-patterns,inheritance,Java,Design Patterns,Inheritance,重组合轻继承 这是一个非常流行的短语。我读了几篇文章,最后每篇文章都说 当类之间存在纯is-A关系时,使用继承 例如: 在苹果和水果之间存在着明确的is-A关系,即苹果是水果,但作者也将其显示为苹果有水果(成分),以显示继承实施时的陷阱 我在这里有些困惑,这句话是什么意思 当类之间存在纯is-A关系时,使用继承 使用组合而不是继承是否意味着总是尝试应用组合,即使存在纯粹的is-a关系,只在组合没有意义的情况下保留继承?我会说不。在水果/苹果场景中,使用继承很有意义。这篇文章的作者也证实了这一点:

重组合轻继承

这是一个非常流行的短语。我读了几篇文章,最后每篇文章都说

当类之间存在纯is-A关系时,使用继承

例如:

苹果水果之间存在着明确的is-A关系,即苹果是水果,但作者也将其显示为苹果有水果(成分),以显示继承实施时的陷阱

我在这里有些困惑,这句话是什么意思

当类之间存在纯is-A关系时,使用继承


使用组合而不是继承是否意味着总是尝试应用组合,即使存在纯粹的is-a关系,只在组合没有意义的情况下保留继承

我会说不。在水果/苹果场景中,使用继承很有意义。这篇文章的作者也证实了这一点:“在上面的例子中,苹果很可能是水果,所以我倾向于使用遗传”


如果您的子类显然是一个超类,那么继承就可以了。但是在实践中,您会发现更多的情况可以通过组合更好地解决。

当您使用继承来重用来自超类的代码时,而不是重写方法并定义另一个多态行为,这通常表明您应该使用组合而不是继承


java.util.Properties
类是继承使用不当的一个很好的例子。它扩展了Hashtable,而不是使用Hashtable存储其属性,以便重用其方法,并避免使用委托重新实现其中的一些方法

我认为这是面向对象设计中讨论最多的一点。正如本文所建议的,组合总是优先于继承。这并不意味着你永远不应该使用继承。你应该把它放在更有意义的地方(这是有争议的)

使用合成有许多优点,其中有两个是:

  • 您将完全控制您的实现。i、 例如,您只能公开打算公开的方法
  • 超类中的任何更改都可以通过仅在类中修改来屏蔽。任何使用您的类的客户端类都不需要进行修改
  • 允许您控制何时加载超类(延迟加载)

当关系是永久性的时,使用继承。不要仅仅为了获得自由行为而使用扩展。这就是他们在is-A示例中所指的内容。仅当扩展类确实是父类的扩展时才进行扩展。有时,它不会被切割和干燥,但一般来说。如果您需要从“正确”类进行扩展,组合也可以在将来提供灵活性

这是一篇关于扩展的古老而伟大的文章:


在文章中,没有这样的短语:

在类之间存在纯is-A关系时使用继承

此外,除了你的帖子,谷歌没有在其他地方找到它

取而代之的是,该条内容如下:

确保继承为is-a关系建模。
我的主要指导思想是,只有在子类是超类时才应该使用继承。在上面的例子中,苹果很可能是水果,所以我倾向于使用继承。


这意味着,如果存在关系,尝试首先使用继承,而不是组合。使用组合而不是继承并没有任何偏好——每一个都适合自己的角色。

另外,我想补充一个例子,在这个例子中,您可以使用组合而不是继承,并动态地向对象添加责任。有效的Java中提到了Decorator模式的例子,在“偏爱组合而不是继承”一项中。以javaapi为例;BufferedReader修饰读卡器(而不是扩展FileReader、PipedReader、FilterReader等),因此能够修饰任何类型的读卡器。缓冲功能在运行时附加到这些读卡器,这是装饰器模式


在这里,通过子类化进行扩展是不切实际的。

我想一个好的指导原则是:

当存在is-A关系时,使用继承。否则,请使用 组成

其原因与面向对象设计中的另一个概念——多态性有关。多态性是许多OOP语言的一个特性,其中一个对象可以用来代替另一个对象,前提是第一个对象的类是第二个对象的子类

为了举例说明,想象一下,如果你有一个功能,可以容纳一种动物。使用继承时,只有一个函数:

void feed( Animal a );
多态性使我们确信,我们输入的任何动物亚类都会被接受。否则,我们将被迫为每种类型编写一个函数。我认为这样做的好处大于它的缺点(例如减少封装)


如果没有is-A关系,我认为多态性不会非常有效。因此,最好使用组合并增强类之间的封装/隔离

“如果您的子类显然是一个超类”?@SimonNickerson“如果
显然是一个
每个都适合于自己的角色。
+1。我认为这意味着这取决于我们在班级之间建立关系的“动机”。如果“仅”用于代码重用,那么
支持组合而不是继承
是有效的,如果动机是模拟类之间实际存在的“实际关系”,那么继承和组合都有各自的角色。如果存在纯粹的is-A关系,“尽管”继承比组合有更多的问题,比如强耦合,或者