




版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
面向对象高级程序相关设计2主要内容5.1继承5.2多态性5.3抽象类和抽象方法5.4接口5.5内部类和匿名类35.1继承5.1.1创建子类5.1.2成员变量的隐藏和方法的重写5.1.3super5.1.4对象的上转型对象45.1.1创建子类继承是一种由已有的类创建新类的机制。利用继承,我们可以先创建一个拥有共同属性的一般类,根据该一般类再创建具有特殊属性的新类。由继承而得到的类称为子类(subclass),被继承的类称为父类(或叫超类,superclass)。直接或间接被继承的类都是父类。子类继承父类的状态和行为,同时也可以修改父类的状态或重写父类的行为,并添加新的状态和行为。Java中不支持多重继承。55.1.1创建子类通过在类的声明中加入extends子句来创建一个类的子类,其格式如下:
classSubClassextendsSuperClass{
……}
上面的代码把SubClass声明为SuperClass的直接子类。如果SuperClass又是某个类的子类,则SubClass同时也是该类的(间接)子类。子类可以继承父类的成员变量和方法。如果缺省extends子句,则该类为的子类。子类可以继承父类中访问权限设定为public、protected、default的成员变量和方法。但是不能继承访问权限为private的成员变量和方法。65.1.1创建子类75.1.1创建子类PublicclassMammalClass{
Stringname,eyeColor;intage;publicMammalClass(){name=“thename”;eyeColor=“black”;age=0;}}85.1.1创建子类注意,MammalClass类拥有来自于DogClass和CatClass的相同属性,包括了name、eyeColor、age等。现在我们可以利用继承重写DogClass和CatClass。publicclassDogClassextendsMammalClass{
booleanhasTail;//name,eyeColor,age已经从父类继承
publicDogClass(){//隐式调用super()name="Chase";
eyeColor="Black";
age=2;hasTail=true;}}95.1.1创建子类【例5-1】
继承的简单例子classFather{//父类
privateintmoney;floatweight,height;Stringhead;Stringspeak(Strings){returns;}}classSonextendsFather{//子类
Stringhand,foot;}Weight,height,head,Speak();Hand,foot105.1.1创建子类【例5-1】
继承的简单例子publicclassTestExtend{publicstaticvoidmain(Stringargs[]){Sonboy=newSon();boy.weight=120f;boy.height=1.8f;boy.head="一个头";boy.hand="两只手";boy.foot="两只脚";System.out.println("我是儿子");System.out.println("我有:"+boy.hand+"、"+boy.foot+"、"+boy.head+"、重"+boy.weight+"、高"+boy.height);}}上面程序运行结果如下:我是儿子我有:两只手、两只脚、一个头、重120.0、高1.8115.1.1创建子类
如果子类和父类不在同一个包中,那么,子类可以继承了父类的protected、public修饰的成员变量做为子类的成员变量,并且也可以继承了父类的protected、public修饰的方法作为子类的方法。另外子类和父类不在同一个包中,则子类不能继承父类的default变量和default方法。
125.1.1创建子类
【例5-2】继承不同包中的类的简单例子//HouseHold.javapackagexing.house;publicclassHouseHold{//家类
protectedStringaddress;//地址保护型
publicStringsurnname;//姓公共型
Stringgivenname;//名缺省
publicHouseHold(Stringadd){address=add;}protectedStringgetAddress(){returnaddress;}voidsetMoney(Stringnewadd){address=newadd;}voidsetAddress(Stringadd){address=add;}}135.1.1创建子类
//Mikey.java:packagexing.friend;importxing.house.HouseHold;publicclassMikeyextendsHouseHold{publicMikey(){super("Starflightstreet110");}publicstaticvoidmain(Stringargs[]){Mikeymikey=newMikey();//mikey.givenname=“Johnson”;//非法
mikey.surnname="Math";//合法.mikey.address="Starflightstreet110";//合法.Stringm=mikey.getAddress();//合法
//mikey.setAddress("Starflightstreet110");//非法.System.out.println(mikey.surnname+":"+m);}}145.1.1创建子类
程序编译和运行过程如下:155.1.2成员变量的隐藏和方法的重写
当我们在子类中定义的成员变量和父类中的成员变量同名时,此时称子类的成员变量隐藏了父类的成员变量。当子类中定义了一个方法,并且这个方法的名字,返回类型,参数个数以及类型和父类的某个方法完全相同时,父类的这个方法将被隐藏,这时我们说重写了父类的方法。子类通过成员变量的隐藏和方法的重写可以把父类的状态和行为改变为自身的状态和行为。165.1.2成员变量的隐藏和方法的重写
例如下面的这段程序就是这样的情况:classSuperClass{//父类
inty;
voidsetY(){y=0;}}classSubClassextendsSuperClass{inty;//父类变量y被隐藏
voidsetY(){//重写父类的方法setY()y=1;
}}175.1.3super
5.1.3super
子类在隐藏了父类的成员变量或重写了父类的方法后,常常还要用到父类的成员变量,或在重写的方法中使用父类中被重写的方法以简化代码的编写,这时就要访问父类的成员变量或调用父类的方法,Java中通过super来实现对父类成员的访问。我们知道,this用来引用当前对象,与this类似,super用来引用当前对象的父类。super的使用可以分为下面三种情况:
1)用来访问父类被隐藏的成员变量,如:
super.variable2)用来调用父类中被重写的方法,如:
super.Method([paramlist]):
3)用来调用父类的构造方法,如:
super([paramlist]);185.1.3super
【例5-3】调用父类的构造方法的例子classA{//类Apublicintn;//公共类型的成员变量
publicA(){ }
publicA(intn){this.n=n;}intmethod(){returnn;}}publicclassBextendsA{//类BpublicB(){super(15);}publicstaticvoidmain(Stringargs[]){AaInstance=newB();intb=aInstance.method();System.out.println("类A中的成员变量:"+b);}}19Super的使用---调用父类的方法classsuperClass{inty;superClass(){y=30;System.out.println("insuperClass:y="+y);}voiddoPrint(){System.out.println("InsuperClass.doPrint()");}}例子5-4调用父类的方法20classsubClassextendssuperClass{inty;subClass(){super();//调用父类的构造方法(多余的)
y=50;System.out.println("insubClass:y="+y);}voiddoPrint(){super.doPrint();//调用父类的方法
System.out.println("insubClass.doPrint()");System.out.println("super.y="+super.y+"sub.y="+y);}}publicclassinviteSuper{publicstaticvoidmain(Stringargs[]){subClasssubSC=newsubClass();subSC.doPrint();}}21对象的上转型对象
假设A类是B类的父类,classBextendsA{……}当我们用子类创建一个对象,并把这个对象的引用放到父类的对象中时,例如
Aa;Aa=newB();
或
Aa;Bb=newB();a=b;
称这个父类对象a,是子类对象b的上转型对象。22对象的上转型对象
对象的上转型对象的实体是子类负责创建的,但上转型对象会失去原对象的一些属性和功能。上转型对象具有如下特点:
1)上转型对象不能操作子类新增的成员变量和子类新增的方法。
2)上转型对象可以操作子类继承或重写的成员变量,也可以使用子类继承的或重写的方法。
3)如果子类重写了父类的某个方法后,当对象的上转对象调用这个方法时一定是调用了这个重写的方法,因为程序在运行时知道,这个上转对象的实体是子类创建的,只不过损失了一些功能而已。不要将父类创建的对象和子类对象的上转型对象相混淆。上转型对象在Java编程中是常见的。
可以将对象的上转型对象再强制转换到一个子类对象,这时,该子类对象又具备了子类所给的所有属性和功能。
23对象的上转型对象
【例5-5】上转型对象的使用classMammal{//哺乳动物类privateintn=40;voidcrySpeak(Strings){System.out.println(s);}}publicclassMonkeyextendsMammal{//猴子类voidcomputer(intaa,intbb){intcc=aa*bb;System.out.println(cc);}voidcrySpeak(Strings){System.out.println("**"+s+"**");}publicstaticvoidmain(Stringargs[]){//mammal是Monkey类的对象的上转型对象.Mammalmammal=newMonkey();mammal.crySpeak("Ilovethisgame");//mammalputer(10,10);//把上转型对象强制转化为子类的对象.Monkeymonkey=(Monkey)mammal;monkeyputer(10,10);}}24对象的上转型对象
上述程序的运行结果为:**Ilovethisgame**100在上述例子中,上转对象mammal调用方法:mammal.crySpeak("Ilovethisgame");得到的结果是”**Ilovethisgame**”。而不是“Ilovethisgame”。因为mammal调用的是子类重写的方法crySpeak。在main()中,如果出现下面的两行代码,那将是错误的:mammal.n=1000;//因为子类本来就没有继承n。mammalputer(10,10);//因为computer方法是子类新增的方法。25第5章面向对象高级程序设计5.1继承5.2多态性5.3抽象类和抽象方法5.4接口5.5内部类和匿名类265.2多态性
多态(Polymorphism)的意思就是用相同的名字来定义不同的方法。在Java中,普通类型的多态为重载,这就意味着可以使几个不同的方法使用相同的名字,这些方法以参数的个数不同、参数的类型不同等方面来进行区分,以使得编译器能够进行识别。重载是Java实现多态性的方式之一。例如:family()方法可以有三个版本,如下:
family(){}family(Stringch){address=ch;}family(Stringch,floatn){address=ch;pay=n;}
这些方法并存于程序中,编译时,编译器根据实参的类型和个数来区分从而调用那个方法。这在其它语言的程序中,如C,那将导致灾难性的错误。275.2多态性【例5-6】构造方法重载的例子classperson{Stringname="Johnson";//姓名
intage=45;//年龄
person(){}
person(Stringa){name=a;}
person(Stringa,intb){name=a;age=b;}publicvoiddisplay(){System.out.println("Name=“+name+","+"Age="+age);}}publicclassPoly{publicstaticvoidmain(String[]args){personko1=newperson();ko1.display();personko2=newperson("Mike");Ko2.display();personko3=newperson("Willian",50);ko3.display();}}285.2多态性
在Java语言中,多态性主要体现在两个方面:由方法重载实现的静态多态性(编译时多态)和方法重写实现的动态多态性(运行时多态),如下:
1)编译时多态
在编译阶段,具体调用哪个被重载的方法,编译器会根据参数的不同来静态确定调用相应的方法。
2)运行时多态
如果子类重写了父类的方法,那么重写方法的调用原则如下:Java运行时系统根据调用该方法的实例,来决定调用哪个方法。对子类的一个实例,如果子类重写了父类的方法,则运行时系统调用子类的方法;如果子类继承了父类的方法(未重写),则运行时系统调用父类的方法。另外,方法重写时应遵循的原则如下:改写后的方法不能比被重写的方法有更严格的访问权限。改写后的方法不能比被重写的方法产生更多的异常。
进行方法重写时必须遵从这两个原则,否则编译器会指出程序出错。295.2多态性【例5-7】方法重写的例子classParent{publicvoidfunction(){
System.out.println("IaminParent!");}}classChildextendsParent{
privatevoidfunction(){System.out.println("IaminChild!");}}publicclassRTpolyTest{publicstaticvoidmain(Stringargs[]){Parentpl=newParent();Parentp2=newChild();p1.function();p2.function();}}305.2多态性编译过程如下:D:\user\chap05>JavacRTpolyTest.javaRTpolyTest.java:8:function()inChildcannotoverridefunction()inParent;attemptingtoassignweakeraccessprivileges;waspublicprivatevoidfunction(){^RTpolyTest.java:16:cannotfindsymbolsymbol:variablep1location:classRTpolyTestp1.function();^2errors可以看出,该程序中实例p2调用function()方法时会导致访问权限的冲突。
31第5章面向对象高级程序设计5.1继承5.2多态性5.3抽象类和抽象方法5.4接口5.5内部类和匿名类325.3抽象类和抽象方法Java语言中,用abstract关键字来修饰一个类时,这个类叫做抽象类。一个abstract类只关心它的子类是否具有某种功能,并不关心该功能的具体实现,功能的具体行为由子类负责实现的。例如:
publicabstractclassDrawing{publicabstractvoiddrawDot(intx,inty);publicvoiddrawLine(intx1,inty1,intx2,inty2){
…………
}}
用abstract来修饰一个方法时,该方法叫做抽象方法。与final类和方法相反,abstract类必须被继承,abstract方法必须被重写。
335.3抽象类和抽象方法
当一个类的定义完全表示抽象的概念时,它不应该被实例化为一个对象。例如Java中的Number类就是一个抽象类,它只表示数字这一抽象概念,只有当它作为整数类Integer或实数类Float等的父类时才有意义。定义一个抽象类的格式如下:
abstractclassabstractClass{
……}
由于抽象类不能被实例化,因此下面的语句会产生编译错误:
newabstractClass();抽象类中可以包含抽象方法,为所有子类定义一个统一的接口,对抽象方法只需声明,而不需实现,因此它没有方法体。其格式如下:
abstractreturnTypeabstractMethod([paramlist));
34使用abstract的另一例子abstractclassAA{abstractvoidcallme();voidmetoo(){System.out.println("InsideA'smetoo()method");}}classBBextendsAA{voidcallme(){System.out.println("InsideB'scallme()method");}}publicclassAAbstract{publicstaticvoidmain(Stringargs[]){AAcc=newBB();//cc为上转型对象
cc.callme();cc.metoo();}}
35第5章面向对象高级程序设计5.1继承5.2多态性5.3抽象类和抽象方法5.4接口5.5内部类和匿名类365.4接口接口定义使用接口的优点37接口声明使用关键字interface来定义一个接口。接口的定义和类的定义很相似,分为接口声明和接口体两部分。1、接口声明接口通过使用关键字interface
来声明。完整的接口定义格式如下:[public]interfaceinterfaceName[extendslistOfSuperInterface]{……}其中public修饰符指明任意类均可以使用这个接口,缺省情况下,只有与该接口定义在同一个包中的类才可以访问这个接口。extends子句与类声明中的extends子句基本相同,不同的是一个接口可以有多个父接口,用逗号隔开,而一个类只能有一个父类。子接口继承父接口中所有的常量和方法。通常接口名称以able或ible结尾,表明接口能完成一定的行为,例如Runnable、Serializable。38接口声明2、接口体接口体中包含常量定义和方法定义两部分。其中常量定义部分定义的常量均具有public、static和final属性。其格式如下:returnTypemethodName([paramlist]);接口中只能进行方法的声明,而不提供方法的实现,所以,方法定义没有方法体,且用分号(;)结尾,在接口中声明的方法具有public和abstract属性。另外,如果在子接口中定义了和父接口同名的常量,则父接口中的常量被隐藏。例如:interfaceSummaryable{finalintMAX=50;//MAX具有public、static、final属性voidprintone(floatx);floatsum(floatx,floaty);}上面这段程序可以以Summaryable.java来保存,也可以写入其它Java程序中。39接口声明3、接口的使用一个类通过使用关键字implements
声明自己使用(或实现)一个或多个接口。如果使用多个接口,用逗号隔开接口名。如
classCalculateextendsComputerimplementsSummary,Substractable{……}类Calculate使用了Summary和Substractable接口,继承了Computer类。如果一个类使用了某个接口,那么这个类必须实现该接口的所有方法,即为这些方法提供方法体。需要注意的如下:1)在类中实现接口的方法时,方法的名字,返回类型,参数个数及类型必须与接口中的完全一致。2)接口中的方法被默认是public,所以类在实现接口方法时,一定要用public来修饰。3)另外,如果接口的方法的返回类型如果不是void的,那么在类中实现该接口方法时,方法体至少要有一个return语句。如果是void型,类体除了两个大括号外,也可以没有任何语句.40使用接口的优点从本质上讲,接口是一种特殊的抽象类,这种抽象类中只包含常量和方法的定义,而没有变量和方法的实现。通过接口使得处于不同层次,甚至互不相关的类可以具有相同的行为。接口其实就是方法定义和常量值的集合。它的优点主要体现在下面几个方面:(1)通过接口可以实现不相关类的相同行为,而不需要考虑这些类之间的层次关系。(2)通过接口可以指明多个类需要实现的方法。(3)通过接口可以了解对象的交互界面,而不需了解对象所对应的类。接口把方法的定义和类的层次区分开来,通过它可以在运行时动态地定位所调用的方法。同时接口中可以实现“多重继承”,且一个类可以实现多个接口。正是这些机制使得接口提供了比多重继承(如C++等语言)更简单、更灵活、而且更强劲的功能。
41使用接口的例子【例5-9】
使用多重接口的例子//MultInterfaces.javainterfaceI1{abstractvoidtest(inti);}//可以去掉的interfaceI2{abstractvoidtest(Strings);}publicclassMultInterfacesimplementsI1,I2{publicvoidtest(inti){System.out.println("InMultInterfaces.I1.test");}publicvoidtest(Strings){System.out.println("InMultInterfaces.I2.test");}publicstaticvoidmain(String[]a){MultInterfacest=newMultInterfaces();t.test(42);t.test("Hello");}}42第5章面向对象高级程序设计5.1继承5.2多态性5.3抽象类和抽象方法5.4接口5.5内部类和匿名类435.5内部类和匿名类5.5.1内部类的定义5.5.2内部类特性5.5.3匿名类445.5.1内部类的定义
简单地说,一个类被嵌套定义于另一个类中,称为嵌套类。在大多数情况下,嵌套类(静态的嵌套类除外)就是内部类(innerclass)。包含内部类的类称为外部类。与一般的类相同,内部类具有自己的成员变量和成员方法。通过建立内部类的对象,可以存取其成员变量和调用其成员方法。例如下面的例子:pubicclassGroupOne{intcount;//外部类的成员变量
publicclassStudent{//声明内部类
Stringname;//内部类的成员变量
publicvoidoutput(){//内部类的成员方法
System.out.println(+"");
}}}455.5.1内部类的定义
实际上,Java语言规范对于内部类有如下的规定:在另一个类或者一个接口中声明一个类。在另一个接口或者一个类中声明一个接口。在一个方法中声明一个类。类和接口声明可嵌套任意深度。从上面的规定中我们可以看出,内部类的定义是非常灵活的。46内部类特性
内部类有如下特性:一般用在定义它的类或语句块之内,在外部引用它时必须给出完整的名称。名称不能与包含它的类名相同。可以使用包含它的外部类的静态成员变量和实例成员变量,也可以使用它所在方法的局部变量。可以定义为abstract。可以声明为private或protected。若被声明为static,就变成了顶层类,不能再使用局部变量。若想在内部类中声明任何static成员,则该内部类必须声明为static。因此外部类与内部类的访问原则是:在外部类中,通过一个内部类的对象引用内部类中的成员;反之,在内部类中可以直接引用它的外部类的成员,包括静态成员、实例成员及私有成员。47【例5-10】内部类和外部类之间的访问publicclassGroupTwo{//例5-10privateintcount;//外部类的私有成员变量
publicclassStudent{//声明内部类
Stringname;publicStudent(Stringn1){name=n1;count++;//存取其外部类的成员变量
}publicvoidoutput(){System.out.println();}}publicvoidoutput(){//外部类的实例成员方法
Students1=newStudent("Johnson");//建立内部类对象"s1.output();//通过s1调用内部类的成员方法
System.out.println("count="+this.count);}publicstaticvoidmain(Stringargs[]){GroupTwog2=newGroupTwo();g2.output();}}48【例5-11】内部类访问外部静态变量publicclassGroupThree{privatestaticintcount;//静态变量GroupThree.count统计班级数量
privateStringname;//实例变量GroupT表示班级名称
publicclassStudent{privateintcount;//实例变量Student.count表示学号
privateStringname;//实例变量S表示学生姓名
publicvoidOutput(intcount){count++;//存取方法的参数,局部变量
this.count++;//通过对象存取Student.countGroupThree.count++;//通过类名存取GroupThree.countGroupThree.this.count++;//通过对象名存取GroupThree.countSystem.out.println(count+""+this.count+""+GroupThree.count+""+GroupThree.this.count++);}}publicStudentaStu()//返回内部类Student的一个对象
{returnnewStudent();}publicstaticvoidmain(Stringargs[]){GroupThreeg3=newGroupThree();g3.count=10;//GroupThree.countGroupThree.Students1=g3.aStu();//在外部创建内部类的对象
s1.Output(5);//完整的内部类标识GroupThree.Student}}49【例5-12】静态公用内部类publicclassGroupFour{publicstaticclassStudent{//定义静态公用内部类
staticintcount;//静态内部类中的静态变量
Stringname;intnumber;//序号
publicStudent(Stringn1){//静态内部类的构造方法
name=n1;count++;number=count;//序号自动增加
}publicvoidoutput(){System.out.println(+"number="+this.number);}}publicstaticvoidmain(Stringargs[]){GroupFour.Students1=newGroupFour.Student("A");s1.output();
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- YC/T 601-2023烟草肥料效应田间试验和评价技术要求
- NB/T 11317-2023供电电压监测系统技术规范
- JJF(纺织)037-2023织物透气量仪校准规范
- 统编版2025年八年级语文下学期期末总复习(专题训练)专题08古诗文阅读(课内篇目)(考题猜想)(学生版+解析)
- 板框压滤机主讲缪金伟01课件
- 考研复习-风景园林基础考研试题带答案详解(考试直接用)
- 风景园林基础考研资料试题及答案详解【新】
- 《风景园林招投标与概预算》试题A附答案详解(基础题)
- 2025-2026年高校教师资格证之《高等教育法规》通关题库附参考答案详解(考试直接用)
- 2025年黑龙江省五常市辅警招聘考试试题题库及答案详解(有一套)
- 2024-2029年中国无溶剂复合机行业市场现状分析及竞争格局与投资发展研究报告
- 汽车维修项目实施方案
- 竞技体育人才队伍建设方案
- 《多联机空调系统工程技术规程》JGJ174-2024
- MOOC 微积分(二)-浙江大学 中国大学慕课答案
- 跨学科学习:一种基于学科的设计、实施与评价
- MOOC 动物营养学-西北农林科技大学 中国大学慕课答案
- 2020年江西省上饶市万年县中小学、幼儿园教师进城考试真题库及答案
- 小区燃气管道施工方案施工方法
- 糖尿病合并尿路感染
- 教学能力比赛学情分析图(源图可编辑)
评论
0/150
提交评论