如何在 UML 中可视化协议和扩展?
How to visualize Protocols and Extensions in UML?
使用 UML 接口来可视化 UML 中的 Swift 协议似乎是合理的。但是我应该如何可视化为特定协议提供默认实现的扩展?我应该只使用继承自该协议的 class,例如 <<extension>>ProtocolName
吗?
扩展存在于某个 class 的范围内,只是向其添加了一些功能。所以我会将扩展名表示为 subclass(最终打包可能是首选)。为了表明它是一个扩展,我会使用刻板印象。对扩展的 class 的依赖在某种程度上是可选的,因为在上下文中它是一个命名约定。
如果扩展将另外遵守某些协议,您只需将实现关系添加到相应的接口 classes。
这是一种表达方式。由于没有用于扩展的原生 UML 构造,您可以相对自由地在这里发明自己的惯用语。
简而言之
Swift 协议原则上是一个 UML 接口:class 不从 interface/protocol 继承任何东西,但必须实现 interface/protocol 承诺的功能.
协议扩展改变了这种语义等价:协议扩展可以提供一致性 classes 将继承的特性。这与 UML 接口不兼容,对应于 semantic of an abstract class。但是使用 abstract classes 会使多重继承变得混乱。刻板印象《协议》似乎更可取。
更多解释
协议
未扩展的swift protocol确实对应于UML接口,尽管措辞略有不同:
Swift: A protocol defines a blueprint of methods, properties, and other requirements that suit a particular task or piece of functionality. The protocol can then be adopted by a class, structure, or enumeration to provide an actual implementation of those requirements.
对比:
UML: An Interface is a kind of Classifier that represents a declaration of a set of public Features and obligations that together constitute a coherent service. An Interface specifies a contract; any instance of a Classifier that realizes the Interface shall fulfill that contract.
Class 扩展
有不同的种类extensions。 class 扩展将功能添加到它们扩展的 class 中。如果扩展名出现在同一个文件中,它甚至可以访问 class.
的私有成员
class MyClass {
func hello()->Void { print ("Hello, World !"); }
}
var c = MyClass()
extension MyClass { // first extension
func hellobye() -> Void { hello(); print(" Good bye!"); }
}
extension MyClass { // second extension
func bye() -> Void { print("Au revoir!"); }
}
c.hello() // the object has all the features of class + extension
c.hellobye() // even if it was defined befor the extension
c.bye()
扩展名没有明确的名称:它只是重新定义了原始类型,class 的行为就好像初始定义和扩展名是相同的 classifier,只是分开了在源代码中:
- 如果扩展和初始 class 在同一个包中定义,在 UML 中表示它的最干净的方法是在 UML 图中丰富初始 class。
- 如果扩展是在另一个包中定义的,您可以将完整的扩展集表示为与自己的 class 相同的 class,以及将两者组合的合并包。由于扩展工作需要原始 class,因此您还可以显示两者之间的依赖关系。或者,您也可以想到
«class extension»
刻板印象。但同样,由于 UML 唯一命名约束,将所有扩展分组到包中的相同 class。
协议扩展
协议扩展改变了底层协议的性质。虽然原始协议是一个没有任何实现的接口,但扩展协议将提供一些实现:
protocol MyProto {
var v1:String { get }
func op1() -> Void
func op2() -> Void
}
class Test : MyProto {
var v1:String = "abc"
func op1() -> Void { print("Op 1"); }
func op2() -> Void { print("Op 2"); }
}
extension MyProto {
var dev1:String { get { return "de"+v1; }}
func combo() -> Void { op1(); op2(); print("Combo 1 and 2"); }
}
var test = Test()
test.combo()
print (test.dev1);
在 UML 中,扩展协议将对应于一个 «abstract»
class,即 class 由于缺少某些功能而无法直接实例化,但可能具有某些功能明确定义的是继承的。 UML 不完全支持这种情况,因为没有将接口转换为抽象的建模方法 class:
最简洁的方法是使用 UML 配置文件,将构造型 «protocol»
定义为 «abstract»
classes 的特殊形式。然后将按照上面对 classes 的解释处理协议扩展,在提到 «class extension»
的情况下使用 «protocol extension»
。
使用 UML 接口来可视化 UML 中的 Swift 协议似乎是合理的。但是我应该如何可视化为特定协议提供默认实现的扩展?我应该只使用继承自该协议的 class,例如 <<extension>>ProtocolName
吗?
扩展存在于某个 class 的范围内,只是向其添加了一些功能。所以我会将扩展名表示为 subclass(最终打包可能是首选)。为了表明它是一个扩展,我会使用刻板印象。对扩展的 class 的依赖在某种程度上是可选的,因为在上下文中它是一个命名约定。
如果扩展将另外遵守某些协议,您只需将实现关系添加到相应的接口 classes。
这是一种表达方式。由于没有用于扩展的原生 UML 构造,您可以相对自由地在这里发明自己的惯用语。
简而言之
Swift 协议原则上是一个 UML 接口:class 不从 interface/protocol 继承任何东西,但必须实现 interface/protocol 承诺的功能.
协议扩展改变了这种语义等价:协议扩展可以提供一致性 classes 将继承的特性。这与 UML 接口不兼容,对应于 semantic of an abstract class。但是使用 abstract classes 会使多重继承变得混乱。刻板印象《协议》似乎更可取。
更多解释
协议
未扩展的swift protocol确实对应于UML接口,尽管措辞略有不同:
Swift: A protocol defines a blueprint of methods, properties, and other requirements that suit a particular task or piece of functionality. The protocol can then be adopted by a class, structure, or enumeration to provide an actual implementation of those requirements.
对比:
UML: An Interface is a kind of Classifier that represents a declaration of a set of public Features and obligations that together constitute a coherent service. An Interface specifies a contract; any instance of a Classifier that realizes the Interface shall fulfill that contract.
Class 扩展
有不同的种类extensions。 class 扩展将功能添加到它们扩展的 class 中。如果扩展名出现在同一个文件中,它甚至可以访问 class.
的私有成员class MyClass {
func hello()->Void { print ("Hello, World !"); }
}
var c = MyClass()
extension MyClass { // first extension
func hellobye() -> Void { hello(); print(" Good bye!"); }
}
extension MyClass { // second extension
func bye() -> Void { print("Au revoir!"); }
}
c.hello() // the object has all the features of class + extension
c.hellobye() // even if it was defined befor the extension
c.bye()
扩展名没有明确的名称:它只是重新定义了原始类型,class 的行为就好像初始定义和扩展名是相同的 classifier,只是分开了在源代码中:
- 如果扩展和初始 class 在同一个包中定义,在 UML 中表示它的最干净的方法是在 UML 图中丰富初始 class。
- 如果扩展是在另一个包中定义的,您可以将完整的扩展集表示为与自己的 class 相同的 class,以及将两者组合的合并包。由于扩展工作需要原始 class,因此您还可以显示两者之间的依赖关系。或者,您也可以想到
«class extension»
刻板印象。但同样,由于 UML 唯一命名约束,将所有扩展分组到包中的相同 class。
协议扩展
协议扩展改变了底层协议的性质。虽然原始协议是一个没有任何实现的接口,但扩展协议将提供一些实现:
protocol MyProto {
var v1:String { get }
func op1() -> Void
func op2() -> Void
}
class Test : MyProto {
var v1:String = "abc"
func op1() -> Void { print("Op 1"); }
func op2() -> Void { print("Op 2"); }
}
extension MyProto {
var dev1:String { get { return "de"+v1; }}
func combo() -> Void { op1(); op2(); print("Combo 1 and 2"); }
}
var test = Test()
test.combo()
print (test.dev1);
在 UML 中,扩展协议将对应于一个 «abstract»
class,即 class 由于缺少某些功能而无法直接实例化,但可能具有某些功能明确定义的是继承的。 UML 不完全支持这种情况,因为没有将接口转换为抽象的建模方法 class:
最简洁的方法是使用 UML 配置文件,将构造型 «protocol»
定义为 «abstract»
classes 的特殊形式。然后将按照上面对 classes 的解释处理协议扩展,在提到 «class extension»
的情况下使用 «protocol extension»
。