《第十三章多重继承和多重替换MultipleInheritanceandMultiple.ppt》由会员分享,可在线阅读,更多相关《第十三章多重继承和多重替换MultipleInheritanceandMultiple.ppt(23页珍藏版)》请在三一办公上搜索。
1、第十三章 多重继承和多重替换Multiple Inheritance and Multiple Substitutability,多重继承当一个子类从一个以上的超类型继承属性和方法多从替代不同类型的对象之间的相互替代,多重继承,现实世界的复杂性,由于一个实体的多哥角色性,在进行泛化抽象时,常常需要从不同角度进行。反之,一个实体可以从不同继承特征,构成多重继承。如图 OT3继承了OT1和OT2的全部特征(属性,操作)OT3是OT1和OT2的一个类型扩展OT3的实例既可以替换OT1实例,也可以替换OT2实例,多重继承的有向无环图 DAG,多重继承构造了一个有向无环图,其总根为ANY类型的层次结构是
2、连通的,没有孤立子,从根可以到达每一个类型结点,反子亦然类型的层次结构是无回路的,即多重继承不支持递归若只有单重继承,则DAG转化为树GOM的多重继承是全继承概念,多重继承带来的问题,(一)操作OP的歧义-操作冲突冲突原因:一个op名字分别在不同父类(祖先)OT1,OT2中说明,操作体不同,则造成子类OT3在全继承情况下,op操作名的二义性。若op在共同的祖先,如OT0中被定义,但在不同的父类型如OT1,OT2中被分别重定义,从而造成在OT3中的二义性。,操作二义性举例,一个操作bonus(奖励)分别在Student和Employee有定义,当一个奖励作用在”TA”上时,究竟应当怎么处理呢?,
3、declare bonus:Student|float declare bonus:Employee-void|float-void code bonusForStudents;code bonusForEmps;define define bonusForStudents(gpaInc)is bonusForEmps(salInc)isself.gpa:=self.gpa*gpaInc;self.salary:=self.salary*salInc;增加一个百分点的GPA;增加一个百分点的Salary,var bestEmp:Employee;bestStudent:Student;myTA
4、,yourTA:TeachAsst;boss:Manager;(1)bestEmp:=myTA;(2)bestEmp.bonus(1.1);!假定应当增加salary(3)bestStudent:=yourTA;(4)bestStudent.bonus(1.05);!假定应当增加gpa(5)boss.bonus(1.5);!不会产生二义性,多重继承的操作冲突解决方案,注意:为了兼容已有程序,不能通过修改超类中的操作名来解决问题解决冲突的方法定义优选权,允许用户指定继承的优先权用户通过对Supertype子句中超类型队列来指定优先权type OT supertypes OT1,OTn is,方法
5、(1)实现选择op的方法:A:首先确定op是否在本类型中被定义B:按DAG图,从优先队列中每一个超类开始,向上扫描每个枝条直到根,顺序检查op名称,首先被遇到的op被选中,解决冲突之方法二-显式重命名,对所继承的同名的操作,分别在当前子类型中重新命名虽然操作op的名字在超类中不能修改,但在当前子类中可以用重命名来代替,不会影响兼容性。Type OTSupertypes OT1(renames op to op1)OTm-1(renames op to opm-1)OTm,is,解决冲突方法三重定义操作,对op进行重新精化有两种选择:A:在当前子类型OT3中重新定义op操作B:在OT3中指定凡遇
6、到op操作实际上将与哪一个超类的op捆绑。define type OT3 supertypes OT1,OT2 is operations refine op implementation define op self.OT1$op();!执行OT1中定义op方法end type OT3;,多重继承带来的冲突二-类型冲突,类型冲突是更严重的且目前无法消解的问题(1)属性类型冲突:从不同的父类分别继承了一个同名但类型不同的属性如OT1.A与OT2.A类型不相容在OT3中对同名不相容的属性错误无法在静态编译时被检查出,只有在运行时才能出现。,(2)操作类型冲突从不同的父类分别继承了一个同名但返回类
7、型不同的操作。Delcare f:OT1|T1Delcare f:OT2|T2对于一个具有OT2 类型的变量O2有一个引用链:O2.f().q(),即函数q将由一个T2类型的实例引用。而函数程序运行时,当O2指向一个OT3实例时,函数f根据优先队列解决方法将选择OT1的方法,其返回一个T1类型实例-与q所要求的相冲突。,类型冲突示例关于方法Skill,Student类型的Skill返回一个浮点值floatEmployee类型的Skill返回的一个字符串var myTA:TeachAst;someStudent:Student;someEmp:Employee;empSkill:string;s
8、tudentSkill:float;(1)someEmp:=myTA;someStudent:=myTA;(2)empSkill:=someEmp.skill;(3)studentSkill:=someStudent.skill,多重继承的优点,多重继承可以支持实体的不同角色的抽象和特征示例:商业营销系统中的商品概念A:商品对象的使用特征-类别,规格,型号,产地,品牌可以逐层抽象B:商品对象的价值特征-进价,售价,利润,成本,供货商,合同也可以从财务处理角度进行管理,多重替换,多重替换是针对某些多重继承不能清楚处理的情况下而采用的另外一种支持多角色实体建模的方法多重继承的局限性:继承使类型间互
9、相矛盾,全继承使类型的属性集合杂乱无章继承可能导致冲突,示例瑞士军刀,瑞士军刀有多个部件,小刀,剪刀,钻,等瑞士军刀可以以它的某一部件的身份出现如瑞士军刀是一把小刀;瑞士军刀是一把剪子;瑞士军刀是一把钻子 等等瑞士军刀的每一个部件可以单独使用,其作用功能完全独立,如一把剪刀,一把小刀,建模分析,用多重继承概念建模第一步:超类模型 Blade,Knife,Material,ScissorBlade,Scissor均有一个canCut操作第二步:瑞士军刀建模:type SwissKnife supertypes Knife,Scissor is;!见下面的讨论 end type SwissKnif
10、e;若采用多重继承方法,缺点为(1)属性杂乱无章,(2)方法canCut重复定义,(3)瑞士军刀的某个部件不能作为一个单独对象来使用,多重替换建模方法,以瑞士军刀为例type SwissKnife Supertype Knife is body knife:Knife;scissor:Scissor;fashion Knife via self.knife;fashion Scissor via self.scissor;end type SwissKnife;语句fashion Scissor via self.scissor 的语义为只要瑞士军刀当作scissor看待,则所有的方法调用均转
11、移到SwissKnife的Scissor部件,多重替换的引用示例,var sk:SwissKnife;k:Knife;s:Scissor;p:WorkPiece;p.create;sk.create;k:=sk;s:=sk;sk.canCut(p);k.canCut(p);s.canCut(p);,代表(representation)问题,替换概念也可以灵活的应用在两个类型之间代表问题示例当总公司召集各部门开会时,其关键在于,要求各部门派一个代表,而并不指定必须是谁部门在开会这种特定条件下,其行为就像一个雇员,例如,一个部门可以插入到会议代表的雇员集合中部门内部需要定义一个“代表”操作,一旦需
12、要一个代表时,该操作可以产生一个具体的雇员,部门和雇员两个类型的替换,类型定义type Department supertype ANY is body members:Employee;manager:Manager;fashion Employee using self.representative;operations declare representative:-Employee;implementation define representative is return self.manager;end type Department;,部门和雇员两个类型的替换,引用的替换var meetingParticipants:EmployeeSet;developmentDep:Department;bigBoss:Manager;someEmp:Employee;meetingParticipants.insert(bigBoss);!no meeting without himmeetingParticipants.insert(developmentDep);!they will send a representationforeach(emp in meetingParticipants)print(emp.name);,