《继承多态与接口.ppt》由会员分享,可在线阅读,更多相关《继承多态与接口.ppt(53页珍藏版)》请在淘文阁 - 分享文档赚钱的网站上搜索。
1、第4章继承、多态与接口4.1继承的概念4.2访问控制符4.3多态性4.4理解final 修饰4.5抽象类和抽象方法4.6接口4.7内嵌类4.8对象引用转换继承的概念 父类或超类。实际上是所有子类的公共域和公共方法的集合 子类,父类的特殊化,是对公共域和方法在功能、内涵方面的扩展和延伸,祖先类的所有成员均将成为子类拥有的“财富”Object 类是所有类的祖先Java继承的实现classStudent/未使用继承privateStringaddress;/籍贯privateStringname;/姓名privateintage;/年龄Stringno;/学号publicStudent(String
2、name1,intage1)name=name1;age=age1;/其它Java继承的实现classStudentextendsPersonStringno;/学号/其它只有no属性是新加入的,其它属性在Person 类中均存在继承关系中构造方法的作用(1)当子类未定义构造方法时,创建对象时将无条件地调用父类的无参构造方法;(2)对于父类的含参数构造方法,子类可以在自己构造方法中使用关键字super 来调用它,但super 调用语句必须是子类构造方法中的第一个可执行语句;(3)子类在自己定义构造方法中如果没有用super明确调用父类的构造方法,则在创建对象时,将自动先执行父类的无参构造方法,
3、然后再执行自己定义的构造方法。以下程序在编译时将出错,为什么?classparentStringmy;publicparent(Stringx)my=x;publicclasssubclassextendsparent例4-1 类的继承中构造方法的调用测试classPerson/Person 类privateStringaddress;/籍贯privateStringname;/姓名privateintage;/年龄publicStringgetName()/获取人名returnname;publicPerson(Stringname1,Stringaddress1,intage1)name=
4、name1;address=address1;age=age1;publicPerson()name=无名氏;例4-1 类的继承中构造方法的调用测试publicclassStudentextendsPersonStringno;/学号publicStudent(Stringname1,Stringaddress1,intage1,Stringno1)super(name1,address1,age1);no=no1;publicstaticvoidmain(Stringa)Studentx=newStudent(张三,江西,25,20012541);System.out.println(nam
5、e=+x.getName();System.out.println(no=+x.no);/Studenty=newStudent();不能使用,子类无该构造方法子类中将隐藏父类的同名变量classparentinta=3;intm=2;publicclasssubclassextendsparentinta=4;intb=1;publicstaticvoidmain(Stringa)subclassmy=newsubclass();System.out.println(a=+my.a+,b=+my.b+,m=+my.m);4.2.1公共访问控制符public 作为类的修饰符,将类声明为公共类,
6、表明它可以被所有的其它类所访问和引用 作为类的成员的访问修饰符,表明在其他类中可以无限制地访问该成员。要真正做到类成员可以在任何地方访问,在进行类设计时必须同时满足两点:首先类被定义为public,其次,类的成员被定义为public。4.2.2缺省访问控制符 没有给出访问控制符情形 该类只能被同一个包中的类访问和引用4.2.3私有访问控制符private 用private 修饰的域或方法只能被该类自身所访问例4-3 测试对私有成员的访问classMyclassprivateinta;/私有变量voiddisplay()System.out.println(a);publicclasstestp
7、ublicstaticvoidmain(Stringarg)Myclassmy=newMyclass();my.a=5;my.display();4.2.4保护访问控制符protected用protected 修饰的成员可以在三种类中所引用:该类本身;与它在同一个包中的其它类;在其它包中的该类的子类。例4-4 测试包的访问控制的一个简单程序文件1:PackageData.java(该文件存放在sub 子目录下)packagesub;publicclassPackageDataprotectedstaticintnumber=1;文件2:Mytest.javaimportsub.*;public
8、classMytestpublicstaticvoidmain(Stringargs)System.out.println(result=+PackageData.number);各类访问控制符的作用可以归纳为表3-1可直接访问修饰同一类中同一包中不同包的子类中其他private Yes 默认Yes Yes protected Yes Yes Yes public Yes Yes Yes Yes4.3.1方法的重载(例)publicclassAprotectedvoidtest(intx,inty)System.out.println(test(int,int):+x+y);protected
9、voidtest(intx)System.out.println(test(int):+x);protectedvoidtest(Stringstr)System.out.println(test(String):+str);publicstaticvoidmain(Stringargs)Aa1=newA();a1.test(hello);a1.test(5,4);4.3.1方法的重载 通过形式参数表的差异来区分 方法调用的匹配原则:1)精确匹配2)自动转换匹配基本类型转换对象引用转换例4-5 方法调用的匹配测试publicclassAprotectedintx=0;protectedvoid
10、test(intx)System.out.println(test(int):+x);protectedvoidtest(Objectobj)System.out.println(test(Object):+obj);protectedvoidtest(Stringstr)System.out.println(test(String):+str);publicstaticvoidmain(Stringargs)Aa1=newA();a1.test(hello);a1.test(5);【思考】如果在以上程序中加上如下方法,并将test(intx)方法注释掉,则调用test(5)如何?protec
11、tedvoidtest(longx)System.out.println(test(long):+x);如果是以下情形,调用test(6.3)?protectedvoidtest(floatx)System.out.println(test(float):+x);4.3.2方法的覆盖 以下类B 定义的方法中,方法覆盖如何?classBextendsAprotectedvoidtest(intx)System.out.println(inB.test(int):+x);protectedvoidtest(Stringx,inty)System.out.println(inB.test(Strin
12、g,int):+x+,+y);【思考】通过子类B 的对象可调用多少test 方法?关于方法覆盖有以下问题值得注意:方法名、参数列表、返回类型完全相同才会产生方法覆盖;如果返回类型不一样编译将报错。方法覆盖不能改变方法的静态与非静态属性。子类中不能将父类非静态方法定义为静态方法,反之也一样。不允许子类中方法的访问修饰符比父类有更多的限制。例如:子类不能将父类的public 方法定义为protected方法。但可以将父类的private 方法在子类中重新定义为public 方法.final 方法不能被覆盖。this-出现在类的实例方法或构造方法中,用来代表使用该方法的对象(1)把当前对象的引用作为
13、参数传递给另一个方法。如:obj.f(this)(2)可以调用当前对象的其它方法或访问当前对象的实例变量。如:this.g();(3)使用this 可以区分当前作用域中同名的不同变量。Stringx;publicTest(Stringx,inta)this.x=x;(4)一个构造方法中调用另一个构造方法。publicTest(finalintx)this(x,0);(1)用Super 访问超类的变量或方法classparentinta=3;voidf()a=a+1;publicclasssubclassextendsparentinta=6;voidf()super.f();a=a+super
14、.a-3;(2)调用超类的构造方法publicclassgraduate_studentextendsStudentDateenterDate;/入校时间publicgraduate_student(Stringname,intage,Dated)super(name,age);enterDate=d;如果有super(),必须放在构造方法的第一条语句子类中调用方法的查找过程以及this 和super 的用法【思考】如果graduate_student 中无toString()方法,则this.toString()将会出现什么情况?4.5final 修饰符 final 作为类修饰符-最终类(不
15、能有子类)用final 修饰方法-不能被子类重新定义 用final 定义常量-只能赋值一次注意:如果将引用类型的变量标记为final,那么该变量固定指向一个对象,但可以改变对象内的属性值。例4-7 常量赋值测试publicfinalclasstestpublicstaticinttotalNumber=5;publicfinalintid;publicintweight;publictest(intweight)id=totalNumber+;this.weight=weight;publicstaticvoidmain(Stringargs)finaltestt=newtest(5);t=n
16、ewtest(4);t.weight=t.weight+2;4.6.1抽象类的定义abstractclass 类名称成员变量;方法()/一般方法abstract 方法();/抽象方法 在抽象类中可以包含一般方法和抽象方法。所有的抽象方法必须存在于抽象类中。抽象类表示的是一个抽象概念,不能被实例化为对象。4.6.2抽象类的实现abstractclassAnimal/抽象类Stringname;abstractpublicintgetLeg();/抽象方法classDogextendsAnimalintleg=4;publicDog(Stringn)name=n;publicintgetLeg()
17、returnleg;4.6.2抽象类的实现(续1)classFishextendsAnimalpublicFish(Stringn)name=n;publicintgetLeg()return0;4.6.2抽象类的实现(续2)publicclasstestpublicstaticvoidmain(Stringargs)Animala=newAnimal3;a0=newDog(dog-A);a1=newFish(“fish-A);a2=newDog(dog-B);for(inti=0;i3;i+)System.out.println(ai.name+has+ai.getLeg()+legs);4
18、.7.1接口定义publicinterface 接口名extends 父接口名列表publicstaticfinal 域类型域名=常量值;publicabstractnative 返回值方法名(参数列表)throw 异常列表;声明接口可给出访问控制符;一个接口还可以继承多个父接口,父接口间用逗号分隔。系统默认接口中所有属性的修饰都是publicstaticfinal;系统默认接口中所有方法的修饰都是publicabstract。4.7.1接口定义举例interfaceShapevoiddraw();/用于绘制形状doublearea();/用于求面积4.7.2接口的实现abstractpubl
19、icclassRectangleimplementsShapeprivatedoublex,y,w,h;publicRectangle(doublex,doubley,doublew,doubleh)this.x=x;this.y=y;this.w=w;this.h=h;publicdoublearea()returnw*h;有关接口的实现,要注意以下问题 一个类可以实现多个接口。接口间用逗号分隔;如果实现某接口的类不是抽象类,则在类的定义部分必须实现指定接口的所有抽象方法;一个类在实现某接口的抽象方法时,必须使用完全相同的方法头;接口的抽象方法的访问限制符默认为public,在实现时要在方法
20、头中显式地加上public 修饰。例4-9 接口应用举例interfaceStartStopvoidstart();voidstop();classConferenceimplementsStartStoppublicvoidstart()(Starttheconference.);publicvoidstop()(Stoptheconference.);例4-9 接口应用举例(续1)classCarimplementsStartStoppublicvoidstart()(Insertkeyinignitionandturn.);publicvoidstop()(Turnkeyinigniti
21、onandremove.);例4-9 接口应用举例(续2)publicclassTestInterfacepublicstaticvoidmain(Stringargs)StartStopss=newCar(),newConference();for(inti=0;iss.length;i+)ssi.start();ssi.stop();二义性问题interfaceFrobfloatv=2.0f;/接口定义classParentintv=3;/父类定义classTestextendsParentimplementsFrobpublicstaticvoidmain(Stringargs)newT
22、est().printV();voidprintV()System.out.println(super.v+Frob.v)/2);例4-10 一个简单例子publicclassOuterOneprivateintx=3;InnerOneino=newInnerOne();publicclassInnerOne/内嵌类privateinty=5;publicvoidinnerMethod()System.out.println(yis+y);publicvoidinnerMethod2()System.out.println(x2is+x);创建内嵌类的对象作为外部类的一个属性成员例4-10 一
23、个简单例子(续)publicvoidOuterMethod()System.out.println(xis+x);ino.innerMethod();ino.innerMethod2();publicstaticvoidmain(Stringarg)OuterOnemy=newOuterOne();my.OuterMethod();调用内嵌类的方法有关说明 内嵌类经过编译后产生的字节码文件名为:OuterOne$InnerOne.class 在内嵌类中可以访问外层类的成员 内嵌类可以使用访问控制符public、protected、private 修饰在外层类中访问内嵌类的方法 方法1:在外层类
24、的成员定义中创建内嵌类的对象,例如:InnerOneino=newInnerOne();然后,在外层类中通过该成员变量ino 访问内嵌类的方法 方法2:在程序的某个方法体中创建内嵌类的对象,然后通过该对象访问内嵌类的成员,如:publicvoidaccessInner()InneroneanInner=newInnerone();anInner.innerMethod();在main 方法中间接创建内嵌类的对象 在main 方法中,要创建内嵌类的对象必须先创建外层类对象,然后通过外层类对象创建内嵌类对象。例如:publicstaticvoidmain(Stringarg)OuterOne.In
25、nerOnei=newOuterOne().newInnerOne();i.innerMethod();在内嵌类中使用this-在内嵌类中,this 指内嵌类的对象,要访问外层类的当前对象须加上外层类名作前缀publicclassAprivateintx=3;publicclassB/内嵌类privateintx=5;publicvoidM(intx)System.out.println(x=+x);System.out.println(this.x=+this.x);=+);/内嵌类结束内嵌类对象外部类的当前对象例4-12 静态内嵌类举例publicclassOutertwoprivates
26、taticintx=3;privateinty=5;publicstaticclassInnertwo/静态内嵌类publicstaticvoidMethod()System.out.println(xis+x);publicvoidMethod2()System.out.println(xis+x);/内嵌类结束publicstaticvoidmain(Stringarg)();newOutertwo.Innertwo().Method2();方法中的内嵌类(例4-13)publicclassOuterTwoprivateintx=3;publicvoidOuterMethod(intm)f
27、inalintn=x+2;classInnerTwo/方法内的内嵌类privateinty=5;publicvoidinnerMethod()System.out.println(yis+y);System.out.println(nis+n);System.out.println(xis+x);/内嵌类结束只能访问外部方法中的常量(带final 修饰)方法中的内嵌类(例4-13 续)InnerTwoin2=newInnerTwo();in2.innerMethod();publicstaticvoidmain(Stringarg)OuterTwomy=newOuterTwo();my.Out
28、erMethod(8);匿名内嵌类interfacesamplevoidtestMethod();publicclassAnonymousInnervoidOuterMethod()newsample()publicvoidtestMethod()System.out.println(justtest);.testMethod();/调用内嵌类中定义的方法-字节码文件为AnonymousInner$1.class。如果有更多的匿名内嵌类将按递增序号命名由接口派生匿名内嵌类,根据该内嵌类创建对象4.9.1对象引用赋值转换Objectx=newApple();Fruitm=newOrange();
29、Applex=newFruit();4.9.1对象引用赋值转换在赋值时允许的转换归纳如下:接口类型可转换为父接口或Object 类;类对象可以转换为父类或该类实现了的接口类型;数组可以转换为Object,也可转换为Cloneable 或Serializable 接口。数组还可转换为一个新数组,但旧数组的元素类型必须能够允许转换为新类型方可。4.9.2对象引用强制转换将父类引用赋值给子类变量时要进行强制转换,这种强制转换在编译时总是认可的,但运行时的情况取决于对象的值Friutx;Appley;Orangem,n;n=newOrange();x=n;m=(Orange)x;y=(Apple)x;作业1)利用随机函数定义10对(x,y)值,由此创建的Point 类实例存入一个数组中,按与原点(0,0)的距离由小到大的顺序输出所有的点及到原点的距离。2)编写一个三角形类,能根据3个实数构造三角形对象,如果三个实数不满足三角形的条件,则自动构造以最小值为边的等边三角形。输入任意三个数,求构造的三角形面积。
限制150内