oop - 合成不是“合成”

标签 oop uml aggregation composition model-associations

组成:一个类可以将其他类的对象作为成员进行引用。这称为合成,有时也称为具有关系。

由Deitel P.J.,Deitel H.M. -Java如何编程第9版。
在本主题中讨论了这种观点:
Prefer composition over inheritance?

组合:复合聚合(组合)是一种“强”聚合形式,具有以下特征:
*它是二进制关联,
*这是整体/部分关系,
*一次最多可将一个零件包含在一个(整个)复合物中,并且
*如果删除一个合成(整个),则所有“合成”零件都将“正常”地删除。

http://www.uml-diagrams.org/composition.html上找到
(实际上,Deitel在同一本书中提出了遵循此想法的UML示例,但没有费心去解释它们之间的区别)。
在本主题中讨论了这种观点:
What is the difference between association, aggregation and composition?
很好,两者都是正确的。这就引入了同音概念的问题。
例如:不要绘制带有组成箭头的UML模型来举例说明第一个定义:在UML中,任何关联都是Deitels第一个定义组成的。
以下是我的问题的某些方面,可能有助于正确回答:
我如何说(知道)我们在谈论哪种构成?
我们在两个定义之间(在上下文中)划清界限的地方是什么?
我可以说第一个是面向对象的编程,第二个是软件工程/建模吗?
UML组合是仅模型概念/行话吗?
UML构成是UML专有的东西吗?还是也应用于编程领域?
如何避免团队中“我们在说什么构成”的误解?
请提供参考文献和证据,这不是哲学/观点问题,而是我要解决的“范围”问题。
这不是“什么是组成”的问题。
编辑:我在想区别是动词x形容词:“组成”一个类(第一个定义)和“一个复合关系”(第二个定义)。

最佳答案

我发现很难解释UML关联和实现引用之间的区别,而又不至少解释一下UML关联的实际含义以及它们可以做什么,因此,我们就开始了。
关联与链接
让我们先看一下UML关联和链接(关联的实例)是什么。

[11.5.3.1]关联指定可能在类型化实例之间发生的语义关系。
[11.8.1.1]链接是引用类型化对象的值的元组。关联对一组链接进行分类,每个链接都是关联的一个实例。链接中的每个值都引用关联对应端类型的一个实例。

因此,以下是有限关联的有效实现。

class Brain { }
class Head { }
a = new Brain;
b = new Head;
link = (new Array).add(a).add(b);

所有权

[9.5.3]如果某个属性是通过ownedAttribute由关联以外的其他分类器拥有的,则它表示分类器的属性。

(注意:类是分类器的子类。)
适航性

[11.5.3.1]最终类拥有的某个协会的终端属性,或者该协会的navigableOwnedEnd表示该协会可以从相对的另一端进行导航;否则,该协会就不能从相反的方向进行导航。可导航性意味着可以从关联另一端的实例有效地访问在运行时参与链接的实例(关联的实例)。实现这种有效访问的精确机制是特定于实现的。如果一端不可导航,则可能会或可能无法从另一端进行访问,如果可以,则可能效率不高。

这些概念为何相关?想象下面的例子。
enter image description here
我们看到brainHead类的属性(黑点表示相反类的所有权),并且可以导航(箭头)。
我们还看到head不是Brain的属性(没有黑点⇒不属于Brain类⇒不是Brain的属性),但是它仍然可以导航。这意味着在UML中,head属性由关联本身持有。
例如,实现可能看起来像这样(关联本身由两个引用的元组表示(请参见前面的链接描述))。
class Head {
  public Brain brain;
}

class Brain {
}

h = new Head;
b = new Brain;
h.brain = b;
link = (new Array).add(h).add(b);

因此,正如您希望开始看到的那样,UML关联不是具有“具有关系”的简单概念。
组成
让我们添加另一个作品,组成。

[11.5.3.1]二进制关联可以表示复合聚合(即整体/部分关系)。组成由isComposite属性表示
[9.9.17]仅当聚合为复合时,isComposite的值才为true。

随着聚合


none-指示该属性没有聚合语义。
shared-指示属性具有共享的聚合语义。共享聚合的精确语义因应用程序区域和建模器而异。
复合-表示属性是复合聚合的,即复合对象负责组成对象的存在和存储


我们再次看到,UML关联明确地指定了难以从实现中感知的概念(例如,谁负责对象管理/销毁)。
模型组成与对象实现组成
因此,从上面的描述中,我们可以对实现组成(具有关系)进行更精确的描述。

[详细说明]组成:一个类可以作为成员引用其他类的对象。这称为合成,有时也称为具有关系。
McConnell [Code Complete 2,6.3]也将has-a关系称为遏制。

但是,他们俩都没有谈论对象(包含容器的,复合对象的)如何彼此关联,谁负责生命周期,或者所包含的元素是否知道容器。
因此,只要说对象具有一个“具有”关系(并称其为“组成”),您实际上就可以指这些对象中的任何一个(还有更多)
enter image description here
因此,如果您在编程中调用某种组合,则几乎可以表示任何关系/引用(或者不是继承),因此单词本身并不是很有用。
另一方面,在UML中,您试图捕获有关对象如何相互关联的所有此类信息。因此,重点在于赋予术语更精确的含义。因此,当您在UML中调用某种组合时,您会想到一个非常特定的has-a关系,其中容器负责所包含项目的生命周期。
UML关联的实现
所有这些额外的概念信息都意味着,实际上甚至没有精确的方法来实现关联。这是有道理的,因为实现方式将取决于目标编程语言或环境(例如,将UML概念用作最终产品的可执行模型)。
作为示例,我可以推荐一篇描述Java的UML关联实现的论文,其中包含诸如多重性,可导航性和可见性Implementing UML Associations in Java等强制性概念。

更多子问题

我如何说(知道)我们在谈论哪种构成?

根据上下文,或者您可以问(不确定时这样做总是一件好事)。我个人听说过仅在区别于继承时才将组合用作“具有关系”。其余的是UML。但是我又在学术界,所以我的观点是有偏见的。

我们在两个定义之间(在上下文中)划清界限的地方是什么?

由于“编程”一词的组合实际上并不意味着任何东西(仅表示它具有-a),所以我建议您自己划清界限,并敦促其他人使用更精确的术语。

我可以说第一个是面向对象的编程,第二个是软件工程/建模吗?

或多或少,这个答案中提到的所有细微差别。

UML组合是仅模型概念/行话吗?
UML构成是UML专有的东西吗?还是也应用于编程领域?

不,您可以在编程中使用它来表示与UML中相同的含义,但是您可能需要更清楚地声明它。例如。 “该类是这些类的组合,因为它管理着它们的生命周期。”
关键是要教人们区分规则的旧的has-a关系和具有更精确语义的关系。

如何避免团队中“我们在说什么构成”的误解?

这是一个非常广泛的问题,您可以将其应用于想要附加特殊含义的任何术语(甚至是软件工程?),并且没有最佳方法。具有团队共享的词汇表(您在域中可能已经有很多特定的术语),并指导人们使用更精确的术语。

带引号的引号是指UML 2.5 Specifications中的部分。

关于oop - 合成不是“合成”,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45271479/

相关文章:

architecture - 哪些企业架构工具支持 DoDAF 2.0?

java - UML 类图关联与依赖关系

sockets - 哪种类型的图用于表示客户端/服务器套接字编程?

r - 快速融化的数据表操作

c++ - 无法将术语添加到列出的列表类

php - 'like' 功能的最佳实践

javascript - 从 html 事件调用 javascript 类方法的正确方法

javascript - 如何在 JavaScript 中正确使用模块模式?

java - Java 嵌套子类实例化声明

node.js - 如何在nodeJS和mongoDB中进行聚合