《Java面向对象编程(3-3).ppt》由会员分享,可在线阅读,更多相关《Java面向对象编程(3-3).ppt(33页珍藏版)》请在淘文阁 - 分享文档赚钱的网站上搜索。
1、第三章面向对象编程3软件工程学院主讲人:张昊13.8 多态多态n什么是多态JAVA里没有多继承,一个类只能有一个父类。一个父类可以有多个子类,而在子类里可以重写父类的方法,每个子类里重写的代码不一样。这样用父类的变量去引用子类的实例,在调用相同的方法时得到的结果不一样,这就是多态多态,也就是调用相同的方法会有不同的结果。2nJava语言允许用父类的变量去引用子类的实例。Animal xiaohuang=new Dog();n/父类变量animal引用一个Animal子类Dog的实例 n我们称Animal是xiaohuang的声明(形式)类型声明(形式)类型nDog是xiaohuang的实际类型
2、实际类型。nAnimal xiaohua=new Cat();/父类变量xiaohua引用另一个Animal子类Cat的实例 用父类的变量去引用子类的实例用父类的变量去引用子类的实例3例1:publicclassFather/父类父类publicvoidhitChild()/父类有一个打孩子方法publicclassSon1extendsFather/子类子类1/重写父类打孩子方法publicvoidhitChild()System.out.println(为什么打我?我做错什么了!);publicclassSon2extendsFather/子类子类2/重写父类打孩子方法publicvoid
3、hitChild()System.out.println(我知道错了,别打了!);publicclassSon3extendsFather/子类子类3/重写父类打孩子方法publicvoidhitChild()System.out.println(我跑,你打不着!);4例1:n/测试类publicclassTestpublicstaticvoidmain(Stringargs)Fatherfather;father=newSon1();father.hitChild();father=newSon2();father.hitChild();father=newSon3();father.hit
4、Child();都调用了相同的方法,出现了不同的结果!这就都调用了相同的方法,出现了不同的结果!这就是是多态多态的表现!的表现!5【3.12】ClassSuperClassvoidmethod1()System.out.println(“method1inSuperClass”);voidmethod2()System.out.println(“method2inSuperClass”);classSubClassextendsSuperClassvoidmethod1()System.out.println(“method1inSubClass”);voidmethod3()System.o
5、ut.println(“method3inSubClass”);6classMainpublicstaticvoidmain(Stringargs)SuperClassa=newSubClass();/声明类型为声明类型为SuperClass,实际类型是实际类型是SubClassa.method1();/method1inSubClass,SubClass对对SuperClass中的中的method1进行了重写进行了重写a.method2();/method2inSuperClass,SubClass中没有中没有method2,只能调只能调用用SuperClass的的method2/a.met
6、hod3();错误错误7n如果我们调用如果我们调用a的的method3()方法,方法,则无法通过编译则无法通过编译。这是因为这是因为java语言为强制类型的语言,编译时会检查形语言为强制类型的语言,编译时会检查形式类型是否提供该方法。式类型是否提供该方法。a的形式类型是的形式类型是SuperClass,不提供不提供method3()方法,虽然方法,虽然a的实际类型有的实际类型有method3()方法,但方法,但编译时只检查形式类型,不检查实际类型编译时只检查形式类型,不检查实际类型。n所以形式类型也称为所以形式类型也称为编译期类型编译期类型,实际类型也称为,实际类型也称为执行执行期类型期类型。
7、注意:8注意:n通常我们不会去写通常我们不会去写“SuperClassa=newSubClass();”n但实际应用中,形式类型和实际类型不同的但实际应用中,形式类型和实际类型不同的情况却往往在不知不觉中发生。情况却往往在不知不觉中发生。n看下例:看下例:9【例3.13】classOtherstaticvoidmethod4(SuperClassa)/a的形式类型是的形式类型是SuperClass,实际类型则不一定是实际类型则不一定是SuperClassa.method1();publicclassMainpublicstaticvoidmain(Stringargs)SubClassb=ne
8、wSubClass();Other.method4(b);/相当于相当于SuperClassa=newSubClass();/*调用类方法调用类方法method4(),需要一个需要一个SuperClass类型的参数类型的参数,而,而传入的参数传入的参数b的实际类型是的实际类型是SubClass,这就造成了形式类型,这就造成了形式类型和实际类型的不一致和实际类型的不一致*/10在在java语言中,多态性体现在两个方面:语言中,多态性体现在两个方面:1.由方法重载实现的静态多态性(编译时多态)由方法重载实现的静态多态性(编译时多态)在编译阶段,要调用哪个被重载的方法,编译器会根在编译阶段,要调用哪
9、个被重载的方法,编译器会根据参数的不同调用相应的方法。据参数的不同调用相应的方法。重载是一个类中多态重载是一个类中多态性的一种表现。性的一种表现。2.方法重写实现的动态多态性(运行时多态)方法重写实现的动态多态性(运行时多态)在在JAVA中可以用父类的变量去引用子类的实例,这中可以用父类的变量去引用子类的实例,这样在调用相同的方法时会得到不同的结果。样在调用相同的方法时会得到不同的结果。重写是父重写是父类与子类之间多态性的一种表现,类与子类之间多态性的一种表现,注意:11重写时必须遵循两个原则:重写时必须遵循两个原则重写时必须遵循两个原则:n重写后的方法不能比被重写的方法有更严格重写后的方法不
10、能比被重写的方法有更严格的访问权限;的访问权限;n重写后的方法不能比被重写的方法有更多的重写后的方法不能比被重写的方法有更多的异常。异常。12 从上面的例子可以加以归纳从上面的例子可以加以归纳p46,多态的(,多态的(方法方法重写实现的动态多态重写实现的动态多态)发生必须是:)发生必须是:(1)有直接或间接继承关系的两个类,子类重写)有直接或间接继承关系的两个类,子类重写父类的方法。父类的方法。(2)实际类型为子类的对象,被当成父类来使用,)实际类型为子类的对象,被当成父类来使用,调用重写方法。调用重写方法。注意:13 java运行时系统根据调用该方法的实例,来决定调用哪个方法。1.对子类的一
11、个实例,如果子类重写了父类的方法,则运行时系统调用子类的方法;2.如果子类继承了父类的方法(未重写),则运行时系统调用父类的方法。重写方法的调用原则重写方法的调用原则143.8.2多态带来的优越性多态带来的优越性 多态是建立在继承的基础上的,没有继多态是建立在继承的基础上的,没有继承,就不会有多态。继承的目的:一是为了承,就不会有多态。继承的目的:一是为了继承程序代码,达到程序代码的复用;二是继承程序代码,达到程序代码的复用;二是为了继承接口,达到接口的复用。为了继承接口,达到接口的复用。153.8.3 多态的机制只能用在实例方法上多态的机制只能用在实例方法上多态机制只能用在多态机制只能用在实
12、例方法实例方法上:上:1.不能用在不能用在成员变量成员变量上。上。对于成员变量,对于成员变量,形式类型决定一切形式类型决定一切,完全和实,完全和实际类型无关际类型无关2.不能用在不能用在类方法类方法上上16【例3.14】多态的机制不能用在成员变量上多态的机制不能用在成员变量上classSuperClassintfield1=a;intfield2=b;classSubClassextendsSuperClassintfield1=c;intfield3=d;publicclassMainpublicstaticvoidmain(Stringargs)SuperClassa=newSubClas
13、s();System.out.println(a.field1);/a,而不是,而不是cSystem.out.println(a.field2);/b/System.out.println(a.field3);错误错误17【例3.15】多态的机制不能用在类方法上多态的机制不能用在类方法上classSuperClassstaticvoidmethod1()System.out.println(“method1inSuperClass”);staticvoidmethod2()System.out.println(“method2inSuperClass”);classSubClassextend
14、sSuperClassstaticvoidmethod1()System.out.println(“method1inSubClass”);staticvoidmethod3System.out.println(“method3inSubClass”);18publicclassMainpublicstaticvoidmain(Stringargs)SuperClassa=newSubClass();a.method1();/结果为结果为method1inSuperClassa.method2();/结果为结果为method2inSuperClass/a.method3();错误错误【例3.1
15、5】193.9 final 和 abstract关键字3.9.1finalfinal可以修饰类、变量和方法。可以修饰类、变量和方法。1.final修饰变量修饰变量用用final关键字修饰的标识符被称为关键字修饰的标识符被称为常量常量。例例finalinta=5;/a为常量为常量注意:修饰成员变量时,定义的同时必须给出初注意:修饰成员变量时,定义的同时必须给出初始值,而修饰局部变量时不做要求。始值,而修饰局部变量时不做要求。20final修饰的标识符被称为修饰的标识符被称为常量常量class aa int b=0;final int a=5;/a是常量,定义的同时必须给出初始值是常量,定义的同时
16、必须给出初始值 void f()b=4;a=4;/出错!出错!212.用用final关键字修饰的类不能被继承关键字修饰的类不能被继承finalclassA/A为最终类,不可以被继承。为最终类,不可以被继承。classBextendsA /出错!出错!用用final关键字修饰类关键字修饰类223.用用final关键字修饰的方法不能被重写关键字修饰的方法不能被重写例如例如:finalintf()classAfinalvoidf()classBextendsAvoidf()/出错,用出错,用final关键字修饰的方法不能被重写关键字修饰的方法不能被重写注意注意:如果一个类为:如果一个类为 final
17、 类,那么它的所有方类,那么它的所有方法都为隐式的法都为隐式的 final 方法方法。用用final关键字修饰方法关键字修饰方法233.9.2abstractabstract可修饰符类和方法可修饰符类和方法1.用用abstract 关键字修饰的类叫做关键字修饰的类叫做抽象类抽象类2.用用abstract 关键字修饰的方法叫做关键字修饰的方法叫做抽象方法抽象方法格式如下:格式如下:abstractclassabstractClass/抽象类abstractreturnTypeabstractMethod(paramlist)/抽象方法24抽象方法抽象方法抽象方法:用:用abstract修饰,只有
18、方法的声明,修饰,只有方法的声明,没有方法体没有方法体如:如:abstractvoidf();注意:注意:抽象方法必须在子类中给出具体实现抽象方法必须在子类中给出具体实现若类中包含了抽象方法,则该类必须被定义为抽象类若类中包含了抽象方法,则该类必须被定义为抽象类抽象方法不能是私有的抽象方法不能是私有的(private)不能是静态的不能是静态的(static)25抽象类:抽象类:用用abstract修饰的类。如:修饰的类。如:abstract class 类名类名/定义抽象类定义抽象类 type var1;/声明数据成员;声明数据成员;void f(int a,int b)/声明方法;声明方法;
19、abstract 返回数据类型返回数据类型 方法名(参数方法名(参数);/声明抽象方法;声明抽象方法;抽象类261.1.不能使用抽象类来创建对象不能使用抽象类来创建对象(抽象类不能实例化)(抽象类不能实例化)2.2.如果一个如果一个类中有抽象方法类中有抽象方法,这个类一定是,这个类一定是抽象类抽象类3.3.如果一个类被声明为抽象类,类体中如果一个类被声明为抽象类,类体中也可以没有抽也可以没有抽象方法象方法4.4.如果一个类继承了抽象类,在这个类中如果一个类继承了抽象类,在这个类中必须实现它必须实现它所继承的抽象类的所有抽象方法所继承的抽象类的所有抽象方法(抽象方法必须被(抽象方法必须被重写)重
20、写)一抽象父类一抽象父类A 定义了两个抽象方法定义了两个抽象方法f1,f2;B、C、D类都类都继承于继承于A,那么,那么B、C、D都要实现方法都要实现方法f1和和f2。抽象类27n抽象类是一种比普通类更高层次的抽象,类似于类的框架n抽象类的作用是为了被继承。n通过抽象类创建的子类具有一定的共性,如都要实现父类中的抽象方法抽象类的作用28例例3.16nabstractclassA/定义抽象类定义抽象类Aninti;nabstractvoidabstractFunc();/声明抽象方法声明抽象方法nvoidnotabstractFunc()/一般方法一般方法ni=0;nSystem.out.pri
21、ntln(“fromA:”+i);nnclassBextendsA/B继承了抽象类继承了抽象类AnvoidabstractFunc()/必须实现必须实现A类中的抽象方法类中的抽象方法ni=1;nSystem.out.println(“fromB:”+i);n29classCextendsB/C继承了类继承了类BvoidabstractFunc()/重写了父类重写了父类B中的方法,而不是中的方法,而不是A类中抽象方法的实类中抽象方法的实现现i=3;System.out.println(“fromC:”+i);classDextendsCpublicstaticvoidmain(Stringarg
22、s)Bb=newB();b.abstractFunc();/fromB:1b.notabstractFunc();/fromA:0Cc=newC();c.abstractFunc();/fromC:3例例3.1630abstractclassEmployeeintbasic=2000;abstractvoidsalary();/抽象方法抽象方法classManagerextendsEmployeevoidsalary()System.out.println(薪资等于+basic*5);classWorkerextendsEmployeevoidsalary()System.out.printl
23、n(薪资等于+basic*2);抽象类使用举例抽象类使用举例31习题1publicClassParentspublicvoidprint()System.out.println(“parents”);publicClassFatherextendsParentspublicvoidprint()System.out.println(“father”);publicClassMotherextendsParentspublicvoidprint()System.out.println(“mother”);32publicClassTestpublicvoidfind(Parentsp)p.print();publicstaticvoidmain(Stringargs)Testt=newTest();Fatherf=newFather();Motherm=newMother();t.find(f);t.find(m);最后的输出结果分别是father和mother习题133
限制150内