




版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
Chapter14
AbstractClassesandInterfaces
抽象类和接口2抽象类例:假设每个与形状有关的类都定义了display方法,用来显示具体对象的形状。ShapeRectTriangleCircleRoundedRect此时,可以利用多态性编写代码,用来显示各种形状:Shape[]shapeBody=newShape[20];shapeBody[0]=newRect();shapeBody[1]=newShape();…for(inti=0;i<20;i++){shapeBody[i].display();}3然而,由于Shape是一个抽象的概念,如果它也有display方法就不太合情理。可以做以下几种考虑:去掉Shape类的display方法损失了多态性的优点。可能导致程序出错,如上例。将Shape类的display方法定义成空语句publicvoiddisplay(){}将Shape类的display方法定义成抽象方法abstractclassShape{ …publicabstractvoiddisplay();}当一个类中包含了抽象的方法,此类就被认为是一个抽象类。此时Shape就不能被实例化了,从而在编译时就避免了采用第1种方法可能出现的错误。4抽象类的特点抽象类中的方法不一定都是抽象的,抽象类中可以包含抽象的方法,也可以包含具体的方法。不能实例化抽象类例:如果Course是抽象类,则以下语句是错误的
Coursec=newCourse();
但是可以声明对Course对象的引用:
Coursex;抽象类有子类的时候,除非子类采用具体的方法替代抽象类中的全部抽象方法,否则子类本身也被自动被认为是抽象的。
抽象类之所以被称之为“抽象”的,是因为抽象类省略了要执行的一种或多种特定行为的细节。5抽象类ΔGeometricObjectCircleCylinderRectangleCircle9.javaCylinder9.javapage3706说明
非抽象类(具体类)不能包含抽象方法。如果抽象父类的子类,没有实现所有的抽象方法,它必须声明为抽象的(在这个类声明的前面加上abstract关键词)。也就是说,在一个由抽象类扩展出来的非抽象类中,所有的抽象方法都必须实现,即使这个子类不使用它们。7说明抽象类不能用new运算符实例化,但仍应定义它的构造方法,这种构造方法将在它子类的构造方法中被调用。例如,GeometricObject
的构造方法在Circle
类和Rectangle
类中被调用。8说明(了解)允许声明没有抽象方法的抽象类。(用于定义新子类)子类可以被声明是抽象的,即使它的父类是具体的。子类可以覆盖它父类的方法,并将其声明为抽象的。(当父类方法中的实现在子类中无效时)9说明不能用new运算符创建抽象类的实例,但是,抽象类可以用作数据类型。下面的语句创建了一个元素是GeometricObject类型的数组:
GeometricObject[]geo=newGeometricObject[10];10接口接口比抽象类更抽象,它仅仅声明了方法。例如:为了教学,对象可能需要提供以下服务:同意教授特定的课程指定课程所使用的教科书定义课程的授课提纲批准特定的学生参加课程学习此时可以建立关于一个Teacher的接口:interfaceTeacher{ publicvoidagreeToTeach(Coursec); publicvoiddesignateTextbook(Textbookb,Coursec); publicsyllabusdefineSyllabus(Coursec); publicbooleanapproveEnrollmen(Students,Coursec);}11有了Teacher接口,就可以把对象的各种类指定为教师例如:可以认为Professor能够教学,Student能够教学,一般的Person也可以教学:classProfessorimplementsTeacher{ Stringname; StingemplyeeId; publicvoidagreeToTeach(Coursec){
//编写代码
} publicvoiddesignateTextbook(Textbookb,Coursec){ //编写代码
} publicsyllabusdefineSyllabus(Coursec){ //编写代码
} publicbooleanapproveEnrollmen(Students,Coursec){ //编写代码
}}12说明:通过这样的定义,Professor类替代了Teacher接口的所有方法,因此Professor类是一个具体的类。但是如果Professor类没有替换所有的接口,则Professor类只能看成是一个抽象的类。编译器会要求在Professor类的前面加上abstract关键字。因此,实现接口实际上就是在创建抽象类的子类时,给抽象方法“加上具体的内容”。接口与抽象类的不同在于:接口只抽象行为而抽象类则要指定属性、具体的方法和抽象的方法。13一个类可以继承自多个接口例如:还有一个Administrator接口:interfaceAdministrator{ publicbooleanapproveNewCourse(Coursec); publichireProfessor(Professorp);}则可以指定类实现Teacher和Administrator接口:classProfessorimplementsTeacher,Administrator{ …}在这种情况下,类需要替代这两个接口所定义的所有方法。14用接口实现多重继承问:为什么Java不支持多重继承?答:因为当一个子类从两个以上的父类继承下来的时候,可能会出现属性和方法重复或冲突的现象。PersonStringnameStudentStringmajorintidProfessorStringtitleStringidProfessorStudentProfessorStudent继承的属性StringnameStringmajorintidStringname(重复)StringtitleStringid(冲突)Professor可以讲课,Student类可以听课,为了描述能讲课的学生定义了ProfessorStudent类。15多重继承时方法也会发生冲突:classA{publicvoidf(){…}}classDextendsB,extendsC{publicvoidh(){f();g();}}classCextendsA{publicvoidg(){…}}classBextendsA{publicvoidg(){…}}
当在D中使用f()时,有B和C二条路径到达A中的f();
在D中调用g();时,无法确定是调用哪个基础类的g()方法16分析:多重继承发生问题原因之一在于属性(数据结构)冲突,也就是存储空间的冲突。由于接口不与任何存储空间相关联,因此可以解决存储空间冲突的问题。对于继承的方法的冲突,当使用接口之后,由于接口只定义了方法的抽象,没有具体的执行代码,因此也不会发生代码冲突的问题。17在此例中把与讲课有关的所有要素提取出来,放入Teacher接口。此时,ProfessorStudent类和Professor类都具有了讲课的能力。语句格式:classProfessorStudentextendsStudentimplementsTeacher{
…}Person类Student类Professor类Teacher接口ProfessorStudent18总结:一个类可以继承自一个抽象类或具体类,以及多个接口。抽象类或具体类接口1接口2接口n…子类
子类只有将接口中声明的所有方法,以及抽象类中所有的抽象方法都进行定义,这个子类才能成为一个“具体”的类,才能实例化。如果你的基础类可以不带任何属性和方法定义时,可以将它定义成一个接口。只有在必须带有属性和方法定义的时候,才采用抽象类或具体类。接口继承自其他接口利用关键字extends,接口可以继承其他接口例如:publicinterfaceNewInterfaceextendsInterface1,Interface2{}1920例2Δ
使用GeometricObject类目标:编写程序,创建两个几何对象,一个圆和一个矩形。调用equalArea方法检查两个对象是否有相同的面积,调用displayGeometricObject方法显示这些对象的信息。TestGeometricObjectpage37321输出结果:Thetwoobjectshavethesamearea?false[Circle]radius=5.0Theareais78.53981633974483Theperimeteris31.41592653589793[Rectangle]width=5.0andheight=3.0Theareais15.0Theperimeteris16.022接口接口(interface)是一种与类相似的结构,只包含常量和抽象方法。接口在许多方面与抽象类相近,但是抽象类出来包含常量和抽象方法之外,还可以包含变量和具体方法。为了区分接口和类,Java采用以下语法声明接口:publicinterfaceInterfaceName{constantdeclarations;/*常量声明*/methodsignatures;/*方法头标志*/}23接口是一个特殊的类
在Java中,接口被看成是特殊的类。和类一样,每个接口编译为独立的字节码文件。接口的使用与抽象类很相似。例如:不能使用new操作符创建一个接口的实例;可以使用接口作为变量的数据类型等。24接口与抽象类
接口中的数据必须是常量;抽象类中的数据可以有常量,也可以有变量。
接口中的方法只有一个头标志,没有实现部分;抽象类中可以有抽象的方法,也可以有具体的方法。Page38425接口与抽象类在接口中,所有的数据域都是public
final
static
的,所有的方法都是public
abstract
的.由于这个原因,这些修饰可以忽略,如下所示:提示:接口中的常量能用下面的方式访问:接口名.常量名
(例如,T1.K).
26接口与抽象类所有的类共享同一个根:Object类,但接口没有共同的根。与类相似,接口也可以定义一个类型。一个接口类型的变量可以引用任何实现该接口的类的实例。如果一个类实现了一个接口,这个接口就类似于该类的一个父类。可以将一个接口当作一个数据类型使用,能够将接口类型的变量转换到它的子类,反过来也可以。27接口与抽象类假设c是Class2类的一个实例,则
c也是
Object,Class1,Interface1,Interface1_1,Interface1_2,Interface2_1,和Interface2_2的实例.28创建自定义接口■publicinterfaceEdible{
/**Describehowtoeat*/
publicStringhowToEat();
}classAnimal{
}
classChickenextendsAnimal
implementsEdible{
publicStringhowToEat(){
return"Fryit";
}
}
classTigerextendsAnimal{
}classFruitimplementsEdible{
publicStringhowToEat(){
return"Eatitfresh";
}
}
classAppleextendsFruit{
publicStringhowToEat(){
return"Makeapplecider";
}
}
classOrangeextendsFruit{
publicStringhowToEat(){
return"Makeorangejuice";
}
}Page37729创建自定义接口publicclassTestEdible{
publicstaticvoidmain(String[]args){
Object[]objects={newTiger(),newChicken(),newApple()};
for(inti=0;i<objects.length;i++)
showObject(objects[i]);
}
publicstaticvoidshowObject(Objectobject){
if(objectinstanceofEdible)
System.out.println(((Edible)object).howToEat());
}
}30Comparable接口//这个接口被定义在java.lang包中packagejava.lang;publicinterfaceComparable{publicintcompareTo(Objecto);}选讲page37831Comparable接口compareTo方法判断这个对象相对于给定对象o的顺序,并且当这个对象小于、等于或大于给定对象时,分别返回一个负整数、0或正整数。选讲32Comparable接口Java类库中的许多类(比如,String和Date)都实现了Comparable接口,定义了对象的自然顺序。如果你查看这些类的源代码,你可以发现这一点:
newString()instanceofStringnewString()instanceofComparablenewjava.util.Date()instanceofjava.util.Datenewjava.util.Date()instanceofComparable选讲33Comparable接口//Max.java:找到两个对象中较大的一个publicclassMax{publicstaticObjectmax(Objecto1,Objecto2){if(((Comparable)o1).compareTo(o2)>0)returno1;elsereturno2;}}为了能够使max方法找出两个对象中的较大者,需要为这些对象的类实现Comparable接口。由于o1声明为Object类型,(Comparable)o1告诉编译器o1转换为Comparable类型,因而可以从o1中调用compareTo方法。34Comparable接口publicclassMax{publicstaticObjectmax(Objecto1,Objecto2){if(((Comparable)o1).compareTo(o2)>0)returno1;elsereturno2;}}调用语句1:Dated1=newDate();Dated2=newDate();Dated3=(Date)Max.max(d1,d2);由于max方法返回Object类型,因此在调用的时候,需要对其进行强制类型转换。调用语句2:Strings1="abcdef";Strings2="abcdee";Strings3=(String)Max.max(s1,s2);35Comparable接口publicclassMax{publicstaticComparablemax(Comparableo1,Comparableo2){if(pareTo(o2)>0)returno1;elsereturno2;}}max方法的第二种写法,与前面的代码功能等价:36举例:Comparable接口的实现
目前我们不能使用max方法得到两个Rectangle类对象中较大的一个,因为Rectangle类没有实现Comparable接口。下面的例子就是在Rectangle类的基础上定义一个ComparableRectangle类,使它具有矩形比较的功能。ComparableRectangle选讲37举例:Comparable接口的实现ComparableRectangleComparableRectanglerectangle1=newComparableRectangle(4,5);ComparableRectanglerectangle2=newComparableRectangle(3,6);System.out.println(Max.max(rectangle1,rectangle2));选讲UML图形符号说明:接口名称及其方法名用斜体书写。虚线和空心三角形用于指向接口。38Cloneable接口packagejava.lang;publicinterfaceCloneable{}Cloneable接口定义在java.lang包中,定义如下:选讲page381
这个接口是空的,称为标记接口(markerinterface)。一个实现了Cloneable接口的类就标记为可复制的,它的对象就可以使用Object类中定义的clone()方法实现克隆功能。39举例Java中的很多类(如Date和Calendar)都实现了Cloneable接口。这样,这些类的实例就能克隆。例如,下列代码:Calendarcalendar=newGregorianCalendar(2007,2,1);CalendarcalendarCopy=(Calendar)calendar.clone();System.out.println("calendar==calendarCopyis"+(calendar==calendarCopy));System.out.println("calendar.equals(calendarCopy)is"+calendar.equals(calendarCopy));
显示:calendar==calendarCopyisfalsecalendar.equals(calendarCopy)istrue
选讲对Date而言,==用来比较引用是否相等,equals用来比较内容是否相等。40实现Cloneable接口若要声明一个实现Cloneable接口的自定义类,该类必须覆盖Object类中的clone()方法。下面程序声明了一个House类,它实现了Cloneable接口和Comparable接口。House选讲41Shallowvs.DeepCopy
浅拷贝和深拷贝Househouse1=newHouse(1,1750.50);Househouse2=(House)house1.clone();shallowcopy选讲42浅拷贝和深拷贝浅拷贝是指当对象的字段值被拷贝时,字段引用的对象不会被拷贝。例如,当House对象被clone之后(浅拷贝),此时会创建一个新的House对象(House2),House2的字段值都从House1复制得到,那么house1和house2对象的whenBulit将引用同一个Date对象。深拷贝是对对象实例中字段引用的对象也进行拷贝的一种方式。若是深拷贝,则应创建一个新的House对象和一个新的Date对象,新的House对象将引用新的Date对象。简单地说,浅拷贝只复制顶级对象,而深拷贝则复制对象及其子对象。选讲43浅拷贝和深拷贝在这个例子中,若希望实现深拷贝,则在定义clone()方法时,应该自己写一段代码,在复制两个对象的字段的同时,还要考虑Date对象的创建。clone方法改写如下:publicObjectclone(){try{ //java.util.Datedate=newjava.util.Date(); Objecto=super.clone(); Datedate=(Date)((House)o).getWhenBuilt().clone(); ((House)o).setWhenBuilt(date); returno;}catch(CloneNotSupportedExceptionex){returnnull;}}选讲说明:需要在House.java的源程序前面增加下列语句,才能正常使用Date类:importjava.util.*;44浅拷贝和深拷贝测试的main方法如下:
publicstaticvoidmain(String[]arg){ Househouse1=newHouse(1,100.0); Househouse2=(House)house1.clone(); if(house1.whenBuilt==house2.whenBuilt) System.out.println("==true"); else System.out.println("==false");
}说明:如果运行结果为true,则说明whenBuilt指向的是同一个对象,是浅拷贝;若结果为false,则说明whenBuilt指向的是不同的对象,是深拷贝。选讲45将基本数据类型处理为对象
(包装类WrapperClasses)Δ由于效率的原因Java中的基本数据类型不作为对象使用。然而,许多Java中的方法需要对象作为参数。(例如,集合类)Java提供了一个方法,可将基本数据类型并入对象或包装成对象。
(例如,将int
类型包装成Integer
类)page38646包装类BooleanCharacterShortByteIntegerLongFloatDouble注意:包装类没有无参构造方法所有包装类对象一旦创建,其内部的值就不可以再改变了。47包装类
每一个包装类覆盖了Object类中定义的toString,equals,和hashCode方法。因为所有的数值包装类和Character
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 兽用器械管理办法
- 内江封闭管理办法
- 内部用餐管理办法
- 内页安全管理办法
- 军营超市管理办法
- 军队票据管理办法
- 农夫产品管理办法
- 农机职称管理办法
- 农村污泥管理办法
- 农村门牌管理办法
- 综合训练01集合与常用逻辑用语(18种题型60题专练)(原卷版)
- 治安纠纷谅解协议书
- 菜品委托开发合同协议
- TSG D7004-2010 压力管道定期检验规则 -公用管道
- Unit 5 Here and now 单元说课 课件 2024-2025学年人教版七年级英语下册
- 2025-2030中国护发素销售预测分析及市场产销供需现状研究报告
- 2025年安徽合肥庐阳国有资产投资控股集团招聘笔试参考题库附带答案详解
- 低压配电柜项目可行性研究报告范文参考
- 内蒙古荣信化工有限公司招聘笔试题库2025
- 基层工会经费收支管理
- 养生炖汤外卖服务行业深度调研及发展战略咨询报告
评论
0/150
提交评论