如何在UML图中表示C++私有继承?
在C ++中,可以创建通过一个子类public,protected或private继承。在 UML 类图中表示这一点的符号是什么?我正在考虑在箭头上贴上标签,但不确定这是否是常见做法。
回答
C++ 中的私有继承是什么?
C++中的私有继承,如:
class B1 {
public:
void test();
...
};
class D1 : private B1 {
public:
void demo() { test(); }
...
};
意味着 的每个实例D1都是 的实例B1,但对外界来说这是隐藏的。这个奇怪的构造旨在通过重用基类的代码来实现派生类,但好像没有继承一样。
因此,与公共继承不同,D1 对象不能用于需要 B1 对象的地方:
B1 *p = new D1; //ouch -> error: ‘B1’ is an inaccessible base of ‘D1’
这是 UML 继承吗?
在 UML 中,当派生类专门化一个更通用的基类时,它意味着以下内容:
类型一致性意味着如果一个 Type 符合另一个 Type,那么第一个 Type 的任何实例都可以用作 TypedElement 的值,该 TypedElement 的类型被声明为第二个 Type。分类器是一种类型,并符合其自身及其所有概括。
因此,在 UML 中,如果 D1 专门(即继承自)B1,则始终可以使用 D1 实例代替 B1 对象。这与 C++ 私有继承不匹配。
此外,接口与其实现之间也没有实现关系,因为 D1 不符合 B1 定义的接口:
BehavioredClassifier 和 Interface 之间的 InterfaceRealization 关系意味着 BehavioredClassifier 通过支持接口拥有的功能集及其任何父接口来符合接口指定的契约。
如何在标准 UML 中表示它?
显然,存在依赖关系:D1 依赖于 B1。所以你可以简单地显示一个依赖项。但这并不能真正帮助掌握那种关系,也不是很有用。(除非您添加注释来解释)
因此,更好的方法是映射 UML 以匹配 C++ 语义。在这方面,您可以设想将私有继承建模为组合关系:
为什么? 因为情况与以下组合替代方案非常相似(尽管不完全):
class B2 {
public:
void test();
...
};
class D2 {
private:
B2 base; // instead of private inheritance
public:
void demo() { base.test(); } // base members accessed via base
...
};
所以我们在这里的 UML 模型中所做的就是明确表示,在任何 D1 实例中,都有一个 B1 子对象不能直接从外部世界访问。
编辑:其他选择?
在以前的和现在已经过时的 UML 1.4 中,泛化关系可能有一个«Implementation»可以满足您需要的构造型,但自 2005 年以来不再受支持,并且可能会误导一些将“实现”与接口相关联的读者:
指定子级继承父级的实现(其属性、操作和方法)但不公开供应商的接口,也不保证支持它们,从而违反了可替换性。这是私有继承,通常仅用于编程实现目的。
在 UML 元模型中稍微挖掘一下,似乎泛化具有isSubstitutable默认情况下为 true的属性。因此,您可以考虑使用您自己的特定于语言的profile,并在其中定义构造型«Private inheritance»和元模型元素«Protected inheritance»的专业化Generalization,两者都使用isSubstituable=false. 这将允许:
这可能是一种非常实用且易读的方式来传达您特定于语言的设计意图,包括 D1 对象不可替代 B1。但请注意,这并非没有风险: isSubsituable仅与运行时承诺有关,实际上对 UML 中公共特性的继承规则没有影响。因此,自动化工具可能会得出与读者不同的结论(这就是我在上面提出另一种方法的原因)。