大家好,我正在尝试理解 UML,但有一些关于它的问题
在 UML 中,用原型标记一个类有什么意义<<abstract>>
?
以及如何将此约束表示为不变量,
我意识到这个线程已经有几年的历史了,但是当它被其他人引用时我才想到它,因为它«abstract»
支持 UML 规范不支持构造型的断言。这个说法不太准确,我想解释一下原因。我将首先阐明什么是抽象类。
抽象类是不包括完整实现的类的定义。因此,抽象类不能直接实例化;它们必须是专门的(继承的)。抽象类通过斜体表示类名和抽象方法,另外还可以选择在类名和/或操作中添加 {abstract} 属性(我们通常说的方法,但方法实际上是“方法" 实现操作的) 是抽象的。
接口实际上是一种特定类型的抽象类:零实现的类。它们的表示法与其他类型的抽象类不同(不要斜体,使用«interface»
关键字,并用虚线表示所有特化箭头)。所以,正如 Christian 在这里所说,抽象类有标准的表示法——至少,在类图中有。
现在,正如 Christian 所说的那样,«abstract»
刻板印象确实不存在,但您也可以根据需要创建它,而且 UML 规范支持这样做。您不太可能有理由(至少在类图中),但您仍然可以。
原型是 UML 的“可扩展机制”(共有三种:原型、标记值和约束)。它允许您更具体地定义某种元素。刻板印象应用于类(实际上是元类,元类是其实例也是类的类)。许多原型是预定义的“标准原型”(在 UML 1.4 中它们被称为“标准元素”)。这些例子是«metaclass»
(同样,一个类,它的实例也是类)和«file»
(在系统开发的上下文中的一个物理文件)。
刻板印象是一种关键字。规范(上层结构2.0,附件 B,第 663 页)对关键字有这样的说法:
UML 关键字是保留字,它是 UML 表示法的组成部分,通常作为附加到 UML 图形元素的文本注释或作为 UML 图中文本行的一部分出现。这些词......不能用于命名用户定义的模型元素,因为这样的命名会导致对模型的模棱两可的解释。例如,关键字“trace”是系统定义的抽象构造型(参见附录 C,“标准构造型”),因此不能用于定义任何用户定义的构造型。
在 UML 中,关键字用于四种不同的目的:
为了将特定的 UML 概念(元类)与共享相同通用图形形式的其他概念区分开来......
为了将 UML 概念(元关联)之间的特定关系与共享相同通用图形形式的其他关系区分开来...
要指定附加到 UML 概念的某些修饰符的值(元属性值)...
表示标准刻板印象(见附件 C,“标准刻板印象”)...
关键字始终包含在 guillemets (
«keyword»
) 中,作为视觉提示,可以更容易地区分何时使用关键字...除了识别关键字之外,guillemets 还用于区分用户配置文件中定义的刻板印象的使用。这意味着:
- 并非所有出现在 guillemets 之间的单词都是关键字(即保留字),并且
- 出现在 guillemets 中的词不一定代表刻板印象。
换句话说,您可以创建任何您想要的刻板印象,只要它不是关键字。由于“抽象”不是关键字,因此您可以创建一个«abstract»
刻板印象。
然而,为了这样做,您将不得不遇到一些麻烦,在 UML 2.0 及更高版本中比在 UML 1.4 中更麻烦。UML 1.4 简单地指出,构造型是 UML 规范的扩展机制。可以简单地定义原型,将其应用到任何想要的 UML 元模型部分,并记录更改。UML 2.0 希望将构造型与 UML 元类的关系形式化(UML 图上的任何项目都是元类,并且是 UML 元模型的一部分)。所以,他们想出了Profiles。此示例图显示了配置文件的工作方式:
现在,那个黑色箭头可能看起来有点奇怪,因为除了这个之外,您在任何上下文中都看不到它。UML 2.0 引入了扩展的概念,它将扩展定义为“用于指示元类的属性通过原型进行扩展”。此黑色箭头表示扩展名。
我将引用 Tom Pender(The UML Bible,Wiley Publishing,2004)来解释这个图,因为他比规范做得更好(我当然无法改进):
它表明一个组件是由一个 Bean 原型扩展的,这是必需的。Bean 原型是一种抽象类型,有两个子类型——实体和会话。因此,Component 的每个实例都必须由 Entity 原型或 Session 原型的实例进行扩展。请记住,构造型是一种可以具有属性的类——在这种情况下,会话构造型具有名为状态的属性。这对应于一个标记定义,其值指定会话的状态。标记值是一个枚举 StateKind,它具有无状态或有状态值。
组件有一个约束,显示在附加到组件符号的注释中,说明组件不能被概括或专门化。
该图还显示了接口元类由 Remote 和 Home 原型扩展。EJB 包有一个约束,显示在包中的注释中,说明 Bean 必须实现一个 Home 接口。
«abstract»
因此,如果您有理由费力地创建它,您确实可以使用刻板印象。任何人可能想要的主要原因是在类图以外的某个地方表示一个抽象类。
不存在刻板印象“抽象”——抽象类应该使用斜体字体来描述。抽象意味着一个类不能被实例化。它需要一个子类来做到这一点。因此,作为伪代码约束,这意味着
for all instances i of MyAbstractClass holds: i.actualClass != MyAbstractClass
或在 ocl 中为 MyAbstractClass 持有
self.allInstances()->forAll(i: MyAbstractClass | i.classifier <> self)
由于您的第一个问题版本中没有显示“抽象”一词,因此我一般扩展了刻板印象:
首先:在学习 UML 时,刻板印象不应该是你首先研究的东西。它们相当复杂。
刻板印象或关键词(都用 表示<<MyStereotype>>
)没有一般意义。它由特定的刻板印象定义。通常,您不能将刻板印象表达为不变量。
但是 UML 的其他一些方面可以以相同的方式显示:来自 UML 元级别的类被标记为,<<metaclass>>
即使它没有构造型甚至是不同的实际类型。刻板印象本身用<<stereotype>>
标记显示(即使它们是特殊类的实例)。
自定义构造型的一个示例可以是“服务”。您可以用它标记代表服务的类。可能有一个约束告诉你“服务”必须实现一个特殊的接口。在这种情况下,您可以将此约束表示为(无聊的)不变量。但可能它甚至只是一个标记。在后一种情况下,您可以使用关键字作为替换。