泛化的概念

如题所述

泛化关系是类元的一般描述和具体描述之间的关系,具体描述建立在一般描述的基础之上,并对其进行了扩展。具体描述完全拥有一般描述的特性、成员和关系, 并且包含补充的信息。例如,抵押是借贷中具体的一种,抵押保持了借贷的基本特性并且加入了附加的特性,如房子可以作为借贷的一种抵押品。一般描述被称作 父,具体描述被称作子,如借贷是父而抵押则是子。泛化在类元(类、接口、数据类型、用例、参与者、信号等等)、包、状态机和其他元素中使用。在类中,术语超 类和子类分别代表父和子。  
泛化有两个用途。第一个用途是用来定义下列情况:当一个变量(如参数或过程变量)被声明承载某个给定类的值时,可使用类(或其他元素)的实例作为值,这被称作可替代性原则(由 Barbara Liskov 提出)。该原则表明无论何时祖先被声明了,则后代的一个实例可以被使用。例如,如果一个变量被声明拥有借贷,那么一个抵押对象就是一个合法的值。
泛化使得多态操作成为可能,即操作的实现是由它们所使用的对象的类,而不是由调用者确定的。这是因为一个父类可以有许多子类,每个子类都可实现定义在类整体集中的同一操作的不同变体。例如,在抵押和汽车借贷上计算利息会有所不同,它们中的每一个都是父类借贷中计算利息的变形。一个变量被声明拥有父类,接着任 何子类的一个对象可以被使用,并且它们中的任何一个都有着自己独特的操作。这一点特别有用,因为在不需要改变现有多态调用的情况下就可以加入新的类。例如,一种新的借贷可被新增加进来,而现存的用来计算利息操作的代码仍然可用。一个多态操作可在父类中声明但无实现,其后代类需补充该操作的实现。这种不完整操作是抽象的(其名称用斜体表示)。
泛化的另一个用途是在共享祖先所定义的成分的前提下允许它自身定义增加的描述,这被称作继承。 继承是一种机制,通过该机制类的对象的描述从类及其祖先的声明部分聚集起来。继承允许描述的共享部分只被声明一次而可以被许多类所共享,而不是在每个类中重复声明并使用它,这种共享机制减小了模型的规模。更重要的是,它减少了为了模型的更新而必须做的改变和意外的前后定义不一致。对于其他成分,如状态、信号和用例,继承通过相似的方法起作用。 每一种泛化元素都有一组继承特性。对于任何模型元素的包括约束。对类元而言,它们同样包括一些特性(如属性、操作和信号接收)和关联中的参与者。一个子类继承了它的所有祖先的可继承的特性。它的完整特性包括继承特性和直接声明的特性。
对 类元而言,没有具有相同特征标记的属性会被多次声明,无论直接的或继承的,否则将发生冲突,且模型形式错误。换而言之,祖先声明过的属性不能被后代再次声 明。如果类的接口一致(具有同样的参数、约束和含义),操作可在多个类中声明。附加的声明是多余的。一个方法在层次结构中可以被多个类声明,附在后代上的 方法替代(重载)在任何祖先中声明过的具有相同特征标记的方法。如果一个方法的两个或多个副本被一个类继承(通过不同类的多重继承),那么它们会发生冲突 并且模型形式错误(一些编程语言允许显式选定其中的一种方法。我们发现如果在后代类中重新定义方法会更简单、安全)。元素中的约束是元素本身及它所有祖先 的约束的联合体,如果它们存在不一致,那么模型形式错误。
在一个具体的类中,每一个继承或声明的操作都必须有一个已定义的方法,无论是直接定义或从祖先那里继承而来的。  
如果一个类元有多个父类,那么它从每一父类那里都可得到继承信息(如图 4-8 )。它的特征(属性、操作和信号)是它的所有父类特征的联合。如果同一个类作为父类出现在多条路径上,那么它的每一个成员中只有它的一个拷贝。如果有着同 样特征的特性被两个类声明,而这两个类不是从同一祖先那里继承来的(即独立声明),那么声明会发生冲突并且模型形式错误。因为经验告诉我们设计者应自行解 决这个问题,所以 UML 不提供这种情形的冲突解决方案。像Eiffel 这样的语言允许冲突被程序设计者明确地解决,这比隐式的冲突解决原则要安全,而这些原则经常使开发者大吃一惊。

温馨提示:答案为网友推荐,仅供参考
相似回答