面向对象继承精选文档.ppt

上传人:石*** 文档编号:44745064 上传时间:2022-09-22 格式:PPT 页数:81 大小:2.83MB
返回 下载 相关 举报
面向对象继承精选文档.ppt_第1页
第1页 / 共81页
面向对象继承精选文档.ppt_第2页
第2页 / 共81页
点击查看更多>>
资源描述

《面向对象继承精选文档.ppt》由会员分享,可在线阅读,更多相关《面向对象继承精选文档.ppt(81页珍藏版)》请在taowenge.com淘文阁网|工程机械CAD图纸|机械工程制图|CAD装配图下载|SolidWorks_CaTia_CAD_UG_PROE_设计图分享下载上搜索。

1、面向对象继承本讲稿第一页,共八十一页9/22/20222n这种把继承作为一种扩展同时也作为一种收缩的思想,正是面向对象技术强大的原因,同时也会在正常的部署中引起混淆。扩展与简化 本讲稿第二页,共八十一页9/22/20223n继承总是向下传递的,因此一个类可以从它上面的多个超类中继承各种属性。n如果Dog是Mammal的派生类,而Mammal又是Animal的派生类,则Dog不仅继承了Mammal的属性,同时也继承了Animal的属性。n派生类可以覆盖从基类继承来的行为。继承是向下传递的 本讲稿第三页,共八十一页9/22/20224n代码复用n概念复用。共享方法的定义。继承的作用本讲稿第四页,共

2、八十一页9/22/20225n检验两个概念是否为继承关系“是一个”检验本讲稿第五页,共八十一页9/22/20226class Parent private:int three;protected:int two;public:int one;Parent()one=two=three=42;void inParent()cout one two three;/all legal;Public,Private and Protected本讲稿第六页,共八十一页9/22/20227class Child:public Parent public:void inChild()cout one;/le

3、galcout two;/legalcout three;/error-not legal;Public,Private and Protected本讲稿第七页,共八十一页9/22/20228void main()Child c;cout c.one;/legalcout c.two;/error-not legalcout c.three;/error-not legalPublic,Private and Protected本讲稿第八页,共八十一页9/22/20229n在静态类型语言中n父类和子类数据类型的关系?1.子类实例必须拥有父类的所有数据成员。2.子类的实例必须至少通过继承实现父类

4、所定义的所有功能。3.这样,在某种条件下,如果用子类实例来替换父类实例,那么将会发现子类实例可以完全模拟父类的行为,二者毫无差异。观察本讲稿第九页,共八十一页9/22/202210n指如果类B是类A的子类,那么在任何情况下都可以用类B来替换类A,而外界毫无察觉。替换原则本讲稿第十页,共八十一页9/22/202211n指符合替换原则的子类关系。n区别于一般的可能不符合替换原则的子类关系子类型本讲稿第十一页,共八十一页9/22/202212n子类有时为了避免继承父类的行为,需要对其进行改写n语法上:子类定义一个与父类有着相同名称且类型签名相同的方法。n运行时:变量声明为一个类,它所包含的值来自于子

5、类,与给定消息相对应的方法同时出现于父类和子类。n改写与替换结合时,想要执行的一般都是子类的方法。改写本讲稿第十二页,共八十一页9/22/202213nJava、Smalltalk等面向对象语言,只要子类通过同一类型签名改写父类的方法,自然便会发生所期望的行为。nC+中,需要父类中使用关键字Virtual来表明这一含义。改写机制本讲稿第十三页,共八十一页9/22/202214n与类一样,接口可以继承于其他接口,甚至可以继承于多个父接口。n虽然继承类和实现接口并不完全相同,但他们非常相似,因此使用继承这一术语来描述这两种行为n抽象方法:介于类和接口之间的概念。n定义方法但不实现。n创建实例前,子

6、类必须实现父类的抽象方法。nJava,C#:abstract C+:virtual接口和抽象类本讲稿第十四页,共八十一页9/22/202215n特殊化(specialization)继承n规范化(specification)继承n构造(Construction)继承 n泛化继承n扩展继承 n限制继承 n变体继承n合并继承(多重继承)继承的形式本讲稿第十五页,共八十一页9/22/202216n很多情况下,都是为了特殊化才使用继承。n在这种形式下,新类是基类的一种特定类型,它能满足基类的所有规范。用这种方式创建的总是子类型,并明显符合可替换性原则。n与规范化继承一起,这两种方式构成了继承最理想的方

7、式,也是一个好的设计所应追求的目标。nWindow-TextWindow特殊化继承本讲稿第十六页,共八十一页9/22/202217n规范化继承用于保证派生类和基类具有某个共同的接口,即所有的派生类实现了具有相同方法界面的方法。n基类中既有已实现的方法,也有只定义了方法接口、留待派生类去实现的方法。派生类只是实现了那些定义在基类却又没有实现的方法。规范化继承本讲稿第十七页,共八十一页9/22/202218n派生类并没有重新定义已有的类型,而是去实现一个未完成的抽象规范。也就是说,基类定义了某些操作,但并没有去实现它。只有派生类才能实现这些操作。n在这种情况下,基类有时也被称为抽象规范类。规范化继

8、承本讲稿第十八页,共八十一页9/22/202219n在Java中,关键字abstract确保了必须要构建派生类。声明为abstract的类必须被派生类化,不可能用new运算符创建这种类的实例。除此之外,方法也能被声明为abstract,同样在创建实例之前,必须覆盖类中所有的抽象方法。n规范化继承可以通过以下方式辨认:基类中只是提供了方法界面,并没有实现具体的行为,具体的行为必须在派生类中实现。nGraphicalObject没有实现关于描绘对象的方法,因此它是一个抽象类。其子类Ball,Wall和Hole通过规范子类化实现这些方法。规范化继承本讲稿第十九页,共八十一页9/22/202220n一

9、个类可以从其基类中继承几乎所有需要的功能,只是改变一些用作类接口的方法名,或是修改方法中的参数列表。n即使新类和基类之间并不存在抽象概念上的相关性,这种实现也是可行的。构造继承 本讲稿第二十页,共八十一页9/22/202221n当继承的目的只是用于代码复用时,新创建的子类通常都不是子类型。这称为构造子类化。n一般为了继承而继承,如利用一些工具类已有的方法。构造子类化本讲稿第二十一页,共八十一页9/22/202222n构造子类化经常违反替换原则(形成的子类并不是子类型)构造子类化本讲稿第二十二页,共八十一页9/22/202223n与特化子类化相反?n派生类扩展基类的行为,形成一种更泛化的抽象。n

10、Window-ColoredWindow泛化子类化本讲稿第二十三页,共八十一页9/22/202224n泛化子类化通常用于基于数据值的整体设计,其次才是基于行为的设计。泛化子类化本讲稿第二十四页,共八十一页9/22/202225n如果派生类只是往基类中添加新行为,并不修改从基类继承来的任何属性,即是扩展继承。(泛化子类化对基类已存在的功能进行修改或扩展,扩展子类化则是增加新功能)n由于基类的功能仍然可以使用,而且并没有被修改,因此扩展继承并不违反可替换性原则,用这种方式构建的派生类还是派生类型。扩展继承 本讲稿第二十五页,共八十一页9/22/202226n如果派生类的行为比基类的少或是更严格时,

11、就是限制继承。n常常出现于基类不应该、也不能被修改时。n限制继承可描述成这么一种技术:它先接收那些继承来的方法,然后使它们无效。n双向队列-堆栈限制继承 本讲稿第二十六页,共八十一页9/22/202227n由于限制继承违反了可替换性原则,用它创建的派生类已不是派生类型,因此应该尽可能不用。限制继承 本讲稿第二十七页,共八十一页9/22/202228n两个或多个类需要实现类似的功能,但他们的抽象概念之间似乎并不存在层次关系。n控制鼠标=控制触摸屏w但是,在概念上,任何一个类作为另一个类的子类都不合适w因此,可以选择其中任何一个类作为父类,并改写与设备相关的代码变体子类化本讲稿第二十八页,共八十一

12、页9/22/202229n但是,通常使用的更好的方法是将两个类的公共代码提炼成一个抽象类,比如PointingDevice,并且让这两个类都继承于这个抽象类。n与泛化子类化一样,但基于已经存在的类创建新类时,就不能使用这种方法了。变体子类化本讲稿第二十九页,共八十一页9/22/202230n可以通过合并两个或者更多的抽象特性来形成新的抽象。n一个类可以继承自多个基类的能力被称为多重继承。n助教合并继承 本讲稿第三十页,共八十一页9/22/202231n创建匿名类的条件w只能创建一个匿名类的实例w匿名类必须继承于父类或接口,并且不需要构造函数进行初始化。p.add(new ButtonAdapt

13、er(“Quit”)public void pressed()System.exit(0););Java语言中的匿名类 本讲稿第三十一页,共八十一页9/22/202232n继承使得构造函数这个过程变得复杂w由于父类和子类都有待执行的初始化代码,在创建新对象时都要执行wJava等语言n只要父类构造函数不需要参数,父类的构造函数和子类的构造函数都会自动地执行。n当父类需要参数时,子类必须显示地提供参数。在java中通过super这个关键字来实现。继承和构造函数 本讲稿第三十二页,共八十一页9/22/202233n子类关系是通过创建新类的声明语句来建立的,但它并未解释子类存在的意义和目的。第10章

14、子类和子类型本讲稿第三十三页,共八十一页9/22/202234n可替换性是面向对象编程中一种强大的软件开发技术。n可替换性的意思是:变量声明时指定的类型不必与它所容纳的值类型相一致。n这在传统的编程语言中是不允许的,但在面向对象的编程语言中却常常出现。可替换性本讲稿第三十四页,共八十一页9/22/202235n如果说新类是已存在类的子类型,那么这个新类不仅要提供已存在类的所有操作,而且还要满足于这个已存在类相关的所有属性。n因此,即使符合堆栈的接口定义,但是不满足堆栈的属性特征,也不是子类型子类与子类型间的差异本讲稿第三十五页,共八十一页9/22/202236n子类型关系是通过行为这个术语描述

15、的,与新类的定义或构造无关。n例如:Dictionary类支持与Array类相同的接口,因此即使Dictionary类与Array类之间并不存在继承关系,但是也可以说Dictionary是Array的子类型。本讲稿第三十六页,共八十一页9/22/202237n面向对象语言的强大之处在于对象可以在运行时动态地改变其行为。n编程语言中,术语静态总是用来表示在编译时绑定于对象并且不允许以后对其进行修改的属性或特征。n术语动态用来表示直到运行时绑定于对象的属性或特征。第11章 静态行为和动态行为本讲稿第三十七页,共八十一页9/22/202238n变量的静态类是指用于声明变量的类。静态类在编译时就确定下

16、来,并且再也不会改变。n变量的动态类指与变量所表示的当前数值相关的类。动态类在程序的执行过程中,当对变量赋新值时可以改变。静态类和动态类本讲稿第三十八页,共八十一页9/22/202239n对于静态类型面向对象编程语言,在编译时消息传递表达式的合法性不是基于接收器的当前动态数值,而是基于接收器的静态类来决定的。nP167 例子静态类型和动态类型的区别本讲稿第三十九页,共八十一页9/22/202240n替换原则可以通过提升数值在继承层次上的位置来体现。n有时则相反,还需要判断一种变量目前所包含的数值是否为类层次中的低层次类。运行时类型决定本讲稿第四十页,共八十一页9/22/202241n做出数值是

17、否属于指定类的决定之后,通常下一步就是将这一数值的类型由父类转换为子类。这一过程称为向下造型,或者反多态,因为这一操作所产生的效果恰好与多态赋值的效果相反。向下造型(反多态)本讲稿第四十一页,共八十一页9/22/202242n静态方法绑定/动态方法绑定n响应消息时对哪个方法进行绑定是由接收器当前所包含的动态数值来决定的。方法绑定本讲稿第四十二页,共八十一页9/22/202243Animal pet;pet=new Dog();pet.speak();pet=new bird();pet.speak();例?本讲稿第四十三页,共八十一页9/22/202244n如果方法所执行的消息绑定是由最近赋值

18、给变量的数值的类型来决定的,那么就称这个变量是多态的。nJava,Smalltalk等变量都是多态的。nC+声明为简单类型的变量,非多态。多态变量?本讲稿第四十四页,共八十一页9/22/2022451.使用指针或引用;2.相关方法声明为virtual;才可以实现多态消息传递。C+本讲稿第四十五页,共八十一页9/22/202246n继承和替换原则的引入对编程语言的影响w类型系统w赋值的含义w等价测试w复制建立w存储分配第12章 替换的本质本讲稿第四十六页,共八十一页9/22/202247n从特定的类实例化对象是需要多少存储空间?内存布局本讲稿第四十七页,共八十一页9/22/202248n引入派生

19、类包含基类所不包含的数据?内存布局本讲稿第四十八页,共八十一页9/22/202249class Window public:virtual void oops();private:int height;int width;class TextWindow:public Window public:virtual void oops();private:char*contents;int cursorLocation;例本讲稿第四十九页,共八十一页9/22/202250nWindow win;n为win分配空间的方案?例本讲稿第五十页,共八十一页9/22/2022511.只分配基类所需的存储空间

20、。2.无论基类还是派生类,都分配可用于所有合法的数值的最大的存储空间。3.只分配用于保存一个指针所需的存储空间。在运行时通过对来分配书之所需的存储空间,同时将指针设为相应的合适值。分配方案本讲稿第五十一页,共八十一页9/22/202252nC+使用最小静态空间分配策略。运行高效?nWindow x;nTextWindow y;nx=y;?最小静态空间分配本讲稿第五十二页,共八十一页9/22/202253n 后果?切割Slicing本讲稿第五十三页,共八十一页9/22/202254nC+保证变量x只能调用定义于Window类中的方法,不能调用定义于TextWindow类中的方法。n定义并实现于W

21、indow类中的方法无法存取或修改定义于子类中的数据,因此不可能出现父类存取子类的情况。最小静态空间分配本讲稿第五十四页,共八十一页9/22/202255n对于指针(引用)变量:当消息调用可能被改写的成员函数时,选择哪个成员函数取决于接收器的动态数值。n对于其他变量:关于调用虚拟成员函数的绑定方式取决于静态类(变量声明时的类),而不取决于动态类(变量所包含的实际数值的类)。C+规则本讲稿第五十五页,共八十一页9/22/202256n变量赋值过程中,数值从子类表示的类型转换为父类所表示的类型。n类似于将整型变量赋值给浮点型变量。n对于基于堆栈的变量,可以确保动态类总是等同于静态类。n所以不能对对

22、象中不存在的字段进行存取。不必考虑赋值过程中的内存数据丢失。解释本讲稿第五十六页,共八十一页9/22/202257n分配变量值可能使用的最大存储空间。最大静态空间分配本讲稿第五十七页,共八十一页9/22/202258n对象大小?n对整个程序扫描?问题本讲稿第五十八页,共八十一页9/22/202259n堆栈中不保存对象值。n堆栈通过指针大小空间来保存标识变量,数据值保存在堆中。n指针变量都具有恒定不变的大小,变量赋值时,不会有任何问题。nSmalltalk、Java都采用该方法。动态内存分配本讲稿第五十九页,共八十一页9/22/202260class Box public int value;B

23、ox x=new Box();x.value=7;Box y=x;y.value=12;/what is x.value?观察本讲稿第六十页,共八十一页9/22/202261n内存分配方法影响赋值的含义:1.复制语义:变量值独立2.指针语义:同一(Java)赋值本讲稿第六十一页,共八十一页9/22/202262n浅复制(shallow copy):共享实例变量。n深复制(deep copy):建立实例变量的新的副本。复制和克隆本讲稿第六十二页,共八十一页9/22/202263nC+:拷贝构造函数nJava:改写clone方法深复制本讲稿第六十三页,共八十一页9/22/202264什么是clon

24、e?在实际编程过程中,我们常常要遇到这种情况:有一个对象A,在某一时刻A中已经包含了一些有效值,此时可能会需要一个和A完全相同新对象B,并且此后对B任何改动都不会影响到A中的值,也就是说,A与B是两个独立的对象,但B的初始值是由A对象确定的。在Java语言中,用简单的赋值语句是不能满足这种需求的。要满足这种需求虽然有很多途径,但实现clone()方法是其中最简单,也是最高效的手段。本讲稿第六十四页,共八十一页9/22/202265 Java的所有类都默认继承java.lang.Object类,在java.lang.Object类中有一个方法clone()。JDK API的说明文档解释这个方法将

25、返回Object对象的一个拷贝。要说明的有两点:一是拷贝对象返回的是一个新对象,而不是一个引用。二是拷贝对象与用new操作符返回的新对象的区别就是这个拷贝已经包含了一些原来对象的信息,而不是对象的初始信息。本讲稿第六十五页,共八十一页9/22/202266什么是影子clone?下面的例子包含三个类UnCloneA,CloneB,CloneMain。CloneB类包含了一个UnCloneA的实例和一个int类型变量,并且重载clone()方法。CloneMain类初始化UnCloneA类的一个实例b1,然后调用clone()方法生成了一个b1的拷贝b2。最后考察一下b1和b2的输出:本讲稿第六十

26、六页,共八十一页9/22/202267package clone;class UnCloneA private int i;public UnCloneA(int ii)i=ii;public void doublevalue()i*=2;public String toString()return Integer.toString(i);class CloneB implements Cloneable public int aInt;public UnCloneA unCA=new UnCloneA(111);public Object clone()CloneB o=null;try o

27、=(CloneB)super.clone();catch(CloneNotSupportedException e)e.printStackTrace();return o;public class CloneMain public static void main(String a)CloneB b1=new CloneB();b1.aInt=11;System.out.println(before clone,b1.aInt=+b1.aInt);System.out.println(before clone,b1.unCA=+b1.unCA);CloneB b2=(CloneB)b1.cl

28、one();b2.aInt=22;b2.unCA.doublevalue();System.out.println(=);System.out.println(after clone,b1.aInt=+b1.aInt);System.out.println(after clone,b1.unCA=+b1.unCA);System.out.println(=);System.out.println(after clone,b2.aInt=+b2.aInt);System.out.println(after clone,b2.unCA=+b2.unCA);/*RUN RESULT:before c

29、lone,b1.aInt=11 before clone,b1.unCA=111=after clone,b1.aInt=11 after clone,b1.unCA=222=after clone,b2.aInt=22 after clone,b2.unCA=222*/本讲稿第六十七页,共八十一页9/22/202268 输出的结果说明int类型的变量aInt和UnCloneA的实例对象unCA的clone结果不一致,int类型是真正的被clone了,因为改变了b2中的aInt变量,对b1的aInt没有产生影响,也就是说,b2.aInt与b1.aInt已经占据了不同的内存空间,b2.aInt是

30、b1.aInt的一个真正拷贝。相反,对b2.unCA的改变同时改变了b1.unCA,很明显,b2.unCA和b1.unCA是仅仅指向同一个对象的不同引用!从中可以看出,调用Object类中clone()方法产生的效果是:先在内存中开辟一块和原始对象一样的空间,然后原样拷贝原始对象中的内容。对基本数据类型,这样的操作是没有问题的,但对非基本类型变量,我们知道它们保存的仅仅是对象的引用,这也导致clone后的非基本类型变量和原始对象中相应的变量指向的是同一个对象。大多时候,这种clone的结果往往不是我们所希望的结果,这种clone也被称为“影子clone”。要想让b2.unCA指向与b2.unC

31、A不同的对象,而且b2.unCA中还要包含b1.unCA中的信息作为初始信息,就要实现深度clone。默认的克隆方法为浅克隆,只克隆对象的非引用类型成员本讲稿第六十八页,共八十一页9/22/202269怎么进行深度clone?把上面的例子改成深度clone很简单,需要两个改变:一是让UnCloneA类也实现和CloneB类一样的clone功能(实现Cloneable接口,重载clone()方法)。二是在CloneB的clone()方法中加入一句o.unCA=(UnCloneA)unCA.clone();本讲稿第六十九页,共八十一页Java的深拷贝和浅拷贝Java中常用的拷贝操作有三个,oper

32、ator=、拷贝构造函数 和 clone()方法9/22/202270本讲稿第七十页,共八十一页预定义非集合类型的拷贝过程int x=1;int y=x;y=2;9/22/202271Integer a=1;Integer a=1;Integer b=a;Integer b=a;b=2;b=2;String m=ok;String m=ok;String n=m;String n=m;n=no;n=no;本讲稿第七十一页,共八十一页9/22/202272Integer a=1;Integer a=1;Integer b=new Integer(a);Integer b=new Integer(

33、a);b=2;b=2;String m=ok;String m=ok;String n=new String(m);String n=new String(m);n=no;n=no;本讲稿第七十二页,共八十一页自定义类型的拷贝过程9/22/202273public class Person implements Cloneablepublic class Person implements Cloneable private int age;private int age;private String name;private String name;public int getAge()pu

34、blic int getAge()return age;return age;public void setAge(int age)public void setAge(int age)this.age=age;this.age=age;public String getName()public String getName()return name;return name;void setName(String name)void setName(String name)this.name=name;this.name=name;测试代码:测试代码:Person p=new Person()

35、;Person p=new Person();p.setAge(32);p.setAge(32);p.setName(p.setName(陈抒陈抒););Person p2=p;Person p2=p;p.setAge(33);p.setAge(33);p.setName(p.setName(老陈老陈););本讲稿第七十三页,共八十一页9/22/202274public class Company public class Company public Company()public Company()public Company(Company c)public Company(Compan

36、y c)name=c.name;name=c.name;person=new Person(c.person);person=new Person(c.person);private String name;private String name;private Person person;private Person person;public Person getPerson()public Person getPerson()return person;return person;public void setPerson(Person person)public void setPer

37、son(Person person)this.person=person;this.person=person;public String getName()public String getName()return name;return name;public void setName(String name)public void setName(String name)this.name=name;this.name=name;Override Override public Object clone()throws public Object clone()throws CloneN

38、otSupportedExceptionCloneNotSupportedException Company c=new Company();Company c=new Company();c.setName(name);c.setName(name);c.setPerson(Person)c.setPerson(Person)person.clone();person.clone();return c;return c;public class Person implements Cloneablepublic class Person implements Cloneable public

39、 Person()public Person()public Person(Person p)public Person(Person p)age=p.age;age=p.age;name=p.name;name=p.name;private int age;private int age;private String name;private String name;public int getAge()public int getAge()return age;return age;public void setAge(int age)public void setAge(int age)

40、this.age=age;this.age=age;public String getName()public String getName()return name;return name;public void setName(String name)public void setName(String name)this.name=name;this.name=name;Override Override public Object clone()throws public Object clone()throws CloneNotSupportedExceptionCloneNotSu

41、pportedException return super.clone();return super.clone();本讲稿第七十四页,共八十一页9/22/202275n相同和同一(古老的笑话)相同本讲稿第七十五页,共八十一页9/22/202276非面向对象语言中已经存在。例C语言char*x=“abc”;char*y=“abc”;if(x=y)例本讲稿第七十六页,共八十一页9/22/202277n相同意义与特定领域相关n面向对象语言允许程序员定义相同检验操作符的含义。n相同检验:将另外一个值作为参数传给一个给定值。n消息传递非对称性?相同检验的悖论本讲稿第七十七页,共八十一页9/22/202

42、278class Foo boolean equals(Object right).Foo a,b;if(a.equals(b)/even if this is trueif(b.equals(a)/no guarantee that this is true非对称性例本讲稿第七十八页,共八十一页9/22/202279n根类中定义相同检验操作符,并可以在子类中改写。n什么类型与参数值相联系?n检验类型并进行类型转换。相同检验的悖论本讲稿第七十九页,共八十一页9/22/202280n类层次不同级别对相同操作符的改写,引起的悖论?相同检验的悖论本讲稿第八十页,共八十一页9/22/202281nParent p Child c 验证p是否等于c由父类方法实现。验证c是否等于p由子类方法实现。n父类方法得到p既等于c1又等于c2,使用子类方法比较c1和c2返回假。np=c,c=p2,但是p!=p2观察本讲稿第八十一页,共八十一页

展开阅读全文
相关资源
相关搜索

当前位置:首页 > 教育专区 > 大学资料

本站为文档C TO C交易模式,本站只提供存储空间、用户上传的文档直接被用户下载,本站只是中间服务平台,本站所有文档下载所得的收益归上传人(含作者)所有。本站仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。若文档所含内容侵犯了您的版权或隐私,请立即通知淘文阁网,我们立即给予删除!客服QQ:136780468 微信:18945177775 电话:18904686070

工信部备案号:黑ICP备15003705号© 2020-2023 www.taowenge.com 淘文阁