![]() |
1
262
它们完全不同。继承是一种 “IS-A” 关系。组成是一个 “HAS-A” .
您通过拥有另一个类的实例来进行组合
不幸的是,纠正这种设计错误为时已晚,因为现在更改继承层次结构将破坏与现有代码的兼容性。
有
我强烈推荐乔希·布洛克的书 有效Java第二版
好的面向对象设计并不是要自由地扩展现有的类。你的第一反应应该是作曲。 参见: |
![]() |
2
170
组成方式
在编程中,这表示为:
|
![]() |
3
28
继承会有多危险? 让我们举个例子
1)如上代码所示,Y类与X类有很强的耦合,如果在超类X中有任何变化,Y类可能会发生剧烈的破坏。假设在将来,类X实现了一个方法工作,其签名如下
更改在类X中完成,但它会使类Y不可编译。所以这种依赖关系可以上升到任何程度,而且非常危险。每次超类可能对其所有子类中的代码没有完全的可见性,子类可能总是注意到超类中发生了什么。因此,我们需要避免这种强烈和不必要的耦合。 构图如何解决这个问题? 让我们通过修改相同的示例来查看
这里我们在Y类中创建X类的引用,并通过创建X类的实例来调用X类的方法。 现在所有的强耦合都消失了。超类和子类现在彼此高度独立。类可以自由地进行在继承情况下很危险的更改。 2)组合的第二个非常好的优点是它提供了方法调用的灵活性,例如:
在使用r引用的测试类中,我可以调用x类和y类的方法。这种灵活性在继承中从未存在过。 3)另一大优势:单元测试
在上面的例子中,如果不知道X实例的状态,可以很容易地使用一些测试数据来模拟它,并且可以很容易地测试所有方法。这在继承中根本不可能实现,因为您严重依赖于超类来获取实例的状态并执行任何方法。 4)我们应该避免继承的另一个很好的原因是Java不支持多重继承。 让我们举个例子来理解这一点:
很高兴知道:
因此,出于以上各种原因,使它成为一种习惯,总是喜欢组合而不是继承。 |
![]() |
4
18
@michael rodrigues给出的答案不正确(我很抱歉,我无法直接发表评论),可能会导致一些混乱。 接口实现 is a form of inheritance …当您实现一个接口时,您不仅继承了所有的常量,还将把对象提交给接口指定的类型;它仍然是一个“ IS-A “关系。如果一辆车 可填充的 “汽车” IS-A “ 可填充的 ,并且可以在代码中使用 可填充 . 组合与继承有本质的区别。 当你用作文的时候,你正在(作为另一个答案笔记)做一个“ HAS-A 两个对象之间的关系,而不是 IS-A “使用继承时所建立的关系 . 所以,从其他问题中的汽车例子来看,如果我想说一辆汽车 有-A “油箱,我将使用以下成分:
希望能消除误解。 |
![]() |
5
14
继承
带出
IS-A
关系。
作文
带出
HAS-A关系
.
策略模式解释了在存在定义特定行为的算法系列的情况下,应该使用组合。
因此我们可以有多个类来实现飞行 如:
如果是为了继承,我们将拥有两种不同的鸟类,它们一遍又一遍地执行飞行功能。所以继承和组成是完全不同的。 |
![]() |
6
7
构图和听起来一样——你通过插入部件来创建一个对象。
编辑
这个答案的其余部分错误地基于以下前提。
因此,使用一些标准的理论组件,您可以构建您的对象。然后你的工作就是填写
继承就像另一条路。从一个完整(或半完整)对象开始,替换或重写要更改的各种位。
例如,
有了继承,一些类已经完全实现了,而另一些类则拥有强制重写的方法。在作曲方面,你什么都没有得到。(但是,如果您碰巧有东西在周围,您可以通过在其他类中调用方法来实现接口)。 组合被认为是更灵活的,因为如果你有一个方法,比如iusesfuel,你可以在其他地方有一个方法(另一个类,另一个项目),它只关心处理可以添加燃料的对象,不管是汽车、船、炉子、烧烤等等。接口要求那些说它们实现了inte的类rface实际上拥有该接口所涉及的方法。例如,
那么你可以在别的地方找个方法
奇怪的例子,但是它表明这个方法不关心它填充的内容,因为对象实现了
如果使用继承,则需要不同的
|
![]() |
7
5
|
![]() |
8
4
作为另一个例子,考虑一个汽车类,这将是一个很好的组合使用,一辆汽车将“有”一个发动机,一个变速器,轮胎,座椅等。它不会扩展任何这些类。 |
![]() |
9
3
遗传 在两个类之间,一个类扩展另一个类 是一个 “关系”。 作文 另一端包含类中另一个类的实例 有一个 “关系”。 作文 Java是有用的,因为它在技术上促进了多重继承。 |
![]() |
10
3
简单来说,聚合意味着有一种关系。 组合是聚合的一种特殊情况 . 以一种更具体的方式,一个受限制的聚合称为组合。当一个对象包含另一个对象时,如果所包含的对象不存在容器对象,则称为组合。 例如:一个班级包含学生。没有班级学生是不可能存在的。学生和学生之间有作文。 为什么使用聚合 代码可重用性 使用聚合时 当没有关系时,代码重用也最好通过聚合来实现。 遗传 继承是父子关系继承意味着是一种关系 Java中的继承是一个对象获取父对象的所有属性和行为的机制。 在Java中使用继承 1代码可重用性。 2在子类中添加额外的特性以及方法重写(这样就可以实现运行时多态性)。 |
![]() |
11
2
构图是指某物由不同的部分组成,它与这些部分有着很强的关系。如果主体死亡,其他人也一样,他们就不能拥有自己的生命。人体就是一个粗略的例子。把心脏拿出来,其他的部分都消失了。 继承就是你获取已经存在的东西并使用它的地方。没有牢固的关系。一个人可以继承他父亲的遗产,但他可以不继承。 我不知道Java,所以我不能提供一个例子,但我可以提供一个概念的解释。 |
![]() |
12
2
虽然继承和组合都提供代码可重用性,但Java中的组成和继承的主要区别在于,构图允许在不扩展代码的情况下重用代码,但是对于继承,必须扩展类以重用代码或功能。这一事实的另一个区别是,通过使用组合,您可以重用代码,即使是不可扩展但继承在这种情况下也不能重用代码的最终类。此外,通过使用组合,您可以重用许多类中的代码,因为它们被声明为一个成员变量,但是继承可以重用一个类的代码形式,因为在爪哇中只能扩展一个类,因为Java中不支持多重继承。你可以在C++中这样做,因为有一个类可以扩展不止一个类。顺便说一句,你应该 在Java中更喜欢组合而不是继承 不仅是我,甚至 约书亚·布洛克 在他的书中有建议 |
![]() |
13
1
我认为这个例子清楚地解释了 遗传 和 作文 . 在这个例子中,使用继承和组合解决了这个问题。作者注意到这样一个事实:在 继承 超类中的更改可能会导致继承它的派生类出现问题。 在那里,当您使用UML进行继承或组合时,您还可以看到表示上的差异。 |
![]() |
14
1
继承与组合。 继承和组合都用于类行为的可重用性和扩展。 继承主要用于族算法编程模型中,如IS-A关系型表示类似的对象。例子。
这些是汽车家族的。 构图表示has-a关系类型。它表示一个对象的能力,如duster有五个齿轮,safari有四个齿轮等。每当我们需要扩展现有类的能力时,就使用构图。 例子 我们需要在除尘器对象中再添加一个齿轮,然后再创建一个齿轮对象并将其组合到除尘器对象中。 除非所有派生类都需要这些功能,否则我们不应该在基类中进行更改。对于这种情况,我们应该使用组合。例如 由B类派生的A类 类C派生的类A 类D派生的类A。 当我们在A类中添加任何功能时,即使C类和D类不需要这些功能,它也可用于所有子类。对于这种情况,我们需要为这些功能创建一个单独的类,并将其组合到所需的类(这里是B类)。 示例如下:
|
![]() |
15
0
组合意味着创建一个与特定类相关的类的对象。 假设学生与会计有关系; 继承是,这是具有扩展功能的前一个类。这意味着这个新类是具有一些扩展特性的旧类。 假设学生是学生,但所有学生都是人。因此,学生和人之间存在着一种关系。这是遗产。 |
![]() |
16
0
不,两者都不同。组合跟随“有-有”关系和继承跟随“是-一”关系。构图最好的例子是战略模式。 |
![]() |
17
0
继承意味着重用一个类的完整功能,在这里,我的类必须使用超级类的所有方法,我的类将与超级类紧密耦合,如果继承,代码将在两个类中复制。 但当我们用作文和另一个班级交谈时,我们可以克服所有这些问题。构图正在将另一个类的属性声明到我们要讨论的类中。以及使用该属性可以从类中获得什么功能。 |