《java继承与多态全解.ppt》由会员分享,可在线阅读,更多相关《java继承与多态全解.ppt(61页珍藏版)》请在taowenge.com淘文阁网|工程机械CAD图纸|机械工程制图|CAD装配图下载|SolidWorks_CaTia_CAD_UG_PROE_设计图分享下载上搜索。
1、8/10/2022第 2 页v全面掌握面向对象的基本特征全面掌握面向对象的基本特征v掌握如何使用继承性来到达软件的重用掌握如何使用继承性来到达软件的重用v深入掌握继承过程中域的隐藏和方法的覆盖技巧深入掌握继承过程中域的隐藏和方法的覆盖技巧v深入掌握抽象类和抽象方法的定义深入掌握抽象类和抽象方法的定义v深入掌握接口的定义和使用技巧深入掌握接口的定义和使用技巧 本章学习要点本章学习要点8/10/2022第 3 页v本章讨论面向对象程序设计另外两个最重要的特点:继承本章讨论面向对象程序设计另外两个最重要的特点:继承和多态。和多态。v继承是面向对象程序设计方法中实现软件重用的一种重要继承是面向对象程序
2、设计方法中实现软件重用的一种重要手段,通过继承可以更有效地组织程序结构,明确类之间手段,通过继承可以更有效地组织程序结构,明确类之间的关系,并充分利用已有的类来创建新类,通过继承可以的关系,并充分利用已有的类来创建新类,通过继承可以实现代码的复用,以完成更复杂的设计、开发。实现代码的复用,以完成更复杂的设计、开发。v多态则可以统一多个相关类的对外接口,并在运行时根据多态则可以统一多个相关类的对外接口,并在运行时根据不同的情况执行不同的操作,提高类的抽象度和灵活性。不同的情况执行不同的操作,提高类的抽象度和灵活性。8/10/202244.1 子类、父类与继承机制8/10/2022第 5 页4.1
3、.1 继承的概念v在类的定义过程中,继承是一种由已有的类创建新类的机在类的定义过程中,继承是一种由已有的类创建新类的机制。继承而得到的类为子类,被继承的类为父类,父类包制。继承而得到的类为子类,被继承的类为父类,父类包括所有直接或间接被继承的类。括所有直接或间接被继承的类。Java中不支持多重继承。中不支持多重继承。v通过在类的声明中加入通过在类的声明中加入extends子句来创建一个类的子类:子句来创建一个类的子类: class SubClass extends SuperClass v如果缺省如果缺省extends子句,则该类为子句,则该类为java.lang.Object的子类。的子类。
4、子类可以继承父类中访问权限设定为子类可以继承父类中访问权限设定为public、 protected、package的成员变量和方法,但是不能继承访问权限为的成员变量和方法,但是不能继承访问权限为private的成员变量和方法。的成员变量和方法。 8/10/2022第 6 页4.1.1 继承的概念v何时选择继承何时选择继承?一个很好的经验:一个很好的经验:“B是一个是一个A吗吗?”如果是则让如果是则让B做做A的子类的子类.http:/ 共享性共享性 即子类可以共享父类的公共域和方法。即子类可以共享父类的公共域和方法。 差异性差异性 即子类和父类一定会存在某些差异,否则就应该是即子类和父类一定会存
5、在某些差异,否则就应该是同一个类。同一个类。 层次性层次性 即由即由Java规定的单继承性,每个类都处于继承关系规定的单继承性,每个类都处于继承关系中的某一个层面。中的某一个层面。8/10/2022第 7 页4.1.2 类的层次vJava语言中类的是有严格的层次结构的。语言中类的是有严格的层次结构的。v除除Object类之外,每个类都继承惟一的父类。这种继承性类之外,每个类都继承惟一的父类。这种继承性性质使得类的层次结构形成了如图所示的一种树状结构。性质使得类的层次结构形成了如图所示的一种树状结构。vObject类定义和实现了类定义和实现了Java系统所需要的众多类的共同行系统所需要的众多类的
6、共同行为,它是所有类的父类,也即这个树状结构中的根类,所为,它是所有类的父类,也即这个树状结构中的根类,所有的类都是由这个类继承、扩充而来的,这个有的类都是由这个类继承、扩充而来的,这个Object类定类定义在义在java.lang包中。包中。 8/10/2022第 8 页4.1.2 类的层次Java语言中类的层次 结构结构8/10/202294.2 继承的实现8/10/2022第 10 页4.2.1 4.2.1 子类的定义子类的定义定义一个子类,即在定义一个类的时候加上定义一个子类,即在定义一个类的时候加上extends关关键字,并在之后带上其父类名,其一般格式为:键字,并在之后带上其父类名
7、,其一般格式为: 类的修饰符类的修饰符 class extends ; ; 这和前面定义类的格式并没有什么区别,只是现在这和前面定义类的格式并没有什么区别,只是现在“extends ”不再是可选项。不再是可选项。8/10/2022第 11 页4.2.1 4.2.1 子类的定义子类的定义vclass point v int x, y;v void getxy( int i, int j) v x=i; y=j;v vvclass circle extends point v double r;v double area()v return 3.14*r*r ; v v8/10/2022第 12
8、页4.2.1 4.2.1 子类的定义子类的定义电话及其子类的继承关系 8/10/2022第 13 页4.2.1 4.2.1 子类的定义子类的定义【例【例4.2】 实现图实现图4.2中电话类的继承结构。为了代码的简中电话类的继承结构。为了代码的简洁,而把注意力集中在我们要讨论的语法机制上,这里洁,而把注意力集中在我们要讨论的语法机制上,这里假设移动电话仅一种,电话的计费方式为:国内长途话假设移动电话仅一种,电话的计费方式为:国内长途话费是市话费的费是市话费的3倍,国际长途话费是市话费的倍,国际长途话费是市话费的9倍。倍。 abstract class Telephone long phoneNu
9、mber; final int local_Call=1; final int distance_Call=3; final int international_Call=9; double balance ; abstract boolean charge_Mode (int call_Mode ) ; double getBalance ( ) return balance ; 8/10/2022第 14 页4.2.2 域的继承与隐藏 v1. 域的继承域的继承v子类可以继承父类的所有非私有域。例如各类电话类所包子类可以继承父类的所有非私有域。例如各类电话类所包含的域分别为:含的域分别为:v
10、Mobile_Phone类类 vlong phoneNumber;vint local_Call;vint distance_Call;vint international_Callvdouble balance; 来自继承父类来自继承父类Telephone的的5个基本域个基本域String networkType;8/10/2022第 15 页4.2.2 域的继承与隐藏 IP_Phone类类 vlong phoneNumber;vint local_Call;vint distance_Call;vint international_Callvdouble balance; 来自继承父类来自
11、继承父类Telephone的的5个基个基本域本域double monthFee;来自继承父类来自继承父类Fixed_Telephone boolearn started; Date expireDate;子类子类IP_Phone类中声明的域类中声明的域8/10/2022第 16 页4.2.2 域的继承与隐藏 Ordinary_phone类类 vlong phoneNumber;vint local_Call;vint distance_Call;vint international_Callvdouble balance; 来自继承父类来自继承父类Telephone的的5个基个基本域本域dou
12、ble monthFee;来自继承父类来自继承父类Fixed_Telephone boolean longdistanceService;boolean internationalService; 子类子类Ordinary_phone类中声明的域类中声明的域8/10/2022第 17 页4.2.2 域的继承与隐藏 v2. 域的隐藏域的隐藏v子类重新定义一个与从父类继承来的域变量完全相同子类重新定义一个与从父类继承来的域变量完全相同的变量,称为域的隐藏。即子类中定义了与父类同名的变量,称为域的隐藏。即子类中定义了与父类同名的域变量,就是子类变量对同名父类变量的隐藏。这的域变量,就是子类变量对同名
13、父类变量的隐藏。这里所谓隐藏是指子类拥有了两个相同名字的变量,一里所谓隐藏是指子类拥有了两个相同名字的变量,一个来自继承父类,另一个由自己定义。在这种情况下,个来自继承父类,另一个由自己定义。在这种情况下,当子类执行继承的父类方法时,处理的是父类的变量,当子类执行继承的父类方法时,处理的是父类的变量,而当子类执行它自己定义的方法时,所操作的就是它而当子类执行它自己定义的方法时,所操作的就是它自定义的变量,而把来自继承父类的变量自定义的变量,而把来自继承父类的变量“隐藏隐藏”起起来了。来了。8/10/2022第 18 页class Aclass B extends A static int da
14、ta_a=3; static int data_a = 5;class C extends B void print_out() System.out.println(“data_a= ”+data_a); System.out.println(“A.data_a= ”+A.data_a); System.out.println(“B.data_a= ”+B.data_a); class demo public static void main(String args) C c = new C( ); c.print_out( ); data_a=5A.data_a=3B.data_a=54.
15、2.2 域的继承与隐藏8/10/2022第 19 页4.2.2 域的继承与隐藏 固定电话固定电话 电话类电话类 剩余金额、电话号码 计费方式、查询余额 座机费 计费方式 普通电话普通电话 是否接通长途 剩余金额 计费方式 隐藏父类的剩余金额例4.3 8/10/2022第 20 页4.2.3 方法的继承与覆盖 1. 方法的继承方法的继承父类的非私有方法可以被子类所继承。根据方法的继承关系,将例4.3中电话类及其各子类所包含的方法列举如下。(1)Telephone类abstract boolean charge_Mode();double getBalance();(2)Fixed_Telepho
16、ne类abstract boolean charge_Mode(); /来自继承父类Telephonedouble getBalance(); /来自继承父类Telephone(3)Ordinary_phone类boolean charge_Mode(); double getBelance(); /来自继承父类Fixed_Telephone8/10/2022第 21 页4.2.3 方法的继承与覆盖v2. 方法的覆盖方法的覆盖方法的覆盖(方法的覆盖(Override)是指子类重定义从父类继承来的一)是指子类重定义从父类继承来的一个同名方法,此时父类的这个方法在子类中将不复存在。个同名方法,此时
17、父类的这个方法在子类中将不复存在。这是子类通过重新定义与父类同名的方法,实现自身的行这是子类通过重新定义与父类同名的方法,实现自身的行为。为。方法覆盖时应遵循的原则方法覆盖时应遵循的原则:(1)覆盖后的方法不能比被覆盖的方法有更严格的访问权限。覆盖后的方法不能比被覆盖的方法有更严格的访问权限。(2)覆盖后的方法不能比被覆盖的方法产生更多的异常覆盖后的方法不能比被覆盖的方法产生更多的异常。8/10/2022第 22 页4.2.3 方法的继承与覆盖class Car int color_number; int door_number; int speed; public void push_bre
18、ak() speed = 0; public void add_oil() class Trash_Car extends Car double amount; public void fill_trash() public void push_break() speed = speed 10; 8/10/2022第 23 页4.2.3 方法的继承与覆盖v 覆盖方法的调用覆盖方法的调用 对于重写的方法,对于重写的方法,Java运行时系统根据调用该方法的实例运行时系统根据调用该方法的实例的类型来决定选择哪个方法调用。的类型来决定选择哪个方法调用。public class DemoCar publ
19、ic static void main( String args ) Car aCar = new Trash_Car( );aCar. push_break( ); 在这里,在这里, 类类Trash_Car中的中的push_break( )方方法将被调用。法将被调用。8/10/2022第 24 页4.2.3 方法的继承与覆盖v方法的覆盖与域的隐藏的不同之处在于:子类隐藏父类的方法的覆盖与域的隐藏的不同之处在于:子类隐藏父类的域只是使之不可见,父类的同名域在子类对象中仍然占有域只是使之不可见,父类的同名域在子类对象中仍然占有自己独立的内存空间;而子类方法对父类同名方法的覆盖自己独立的内存空间;
20、而子类方法对父类同名方法的覆盖将清除父类方法占用的内存空间,从而使父类方法在子类将清除父类方法占用的内存空间,从而使父类方法在子类对象中不复存在。对象中不复存在。v域的隐藏和方法的覆盖的意义在于:通过隐藏域和覆盖方域的隐藏和方法的覆盖的意义在于:通过隐藏域和覆盖方法可以把父类的状态和行为改为自身的状态和行为,对外法可以把父类的状态和行为改为自身的状态和行为,对外统一名字与接口,又不失其继承性。统一名字与接口,又不失其继承性。8/10/2022254.3 多 态 性8/10/2022第 26 页v多态性是面向对象程序设计的又一个重要的技术和手段。多态性是面向对象程序设计的又一个重要的技术和手段。
21、 v多态性是指同名的不同方法在程序中共存。即为同一个方多态性是指同名的不同方法在程序中共存。即为同一个方法定义几个版本,运行时根据不同情况执行不同的版本。法定义几个版本,运行时根据不同情况执行不同的版本。调用者只需使用同一个方法名,系统会根据不同情况,调调用者只需使用同一个方法名,系统会根据不同情况,调用相应的不同方法,从而实现不同的功能。用相应的不同方法,从而实现不同的功能。v多态性又被称为多态性又被称为“一个名字,多个方法一个名字,多个方法”。8/10/2022第 27 页4.3.1 4.3.1 多态性的概念多态性的概念多态性的实现有两种方式:多态性的实现有两种方式:(1)覆盖实现多态性)
22、覆盖实现多态性通过子类对继承父类方法的重定义来实现。使用时注意:在通过子类对继承父类方法的重定义来实现。使用时注意:在子类重定义父类方法时,要求与父类中方法的原型(参数个子类重定义父类方法时,要求与父类中方法的原型(参数个数、类型、顺序)完全相同。数、类型、顺序)完全相同。(2)重载实现多态性)重载实现多态性通过定义类中的多个同名的不同方法来实现。编译时是根据通过定义类中的多个同名的不同方法来实现。编译时是根据参数(个数、类型、顺序)的不同来区分不同方法的。参数(个数、类型、顺序)的不同来区分不同方法的。8/10/2022第 28 页4.3.2 覆盖实现多态性在覆盖实现多态性的方式中,子类重定
23、义父类方法,此时方在覆盖实现多态性的方式中,子类重定义父类方法,此时方法的名字、参数个数、类型、顺序完全相同,那么如何区别法的名字、参数个数、类型、顺序完全相同,那么如何区别这些同名的不同方法呢?这些同名的不同方法呢?由于这些方法是存在于一个类层次结构的不同类中的,在调由于这些方法是存在于一个类层次结构的不同类中的,在调用方法时只需要指明调用哪个类(或对象)的方法,就很容用方法时只需要指明调用哪个类(或对象)的方法,就很容易把它们区分开来,其调用形式为:易把它们区分开来,其调用形式为: 对象名对象名.方法名方法名 类名类名.方法名方法名例如,例如,IP电话的计费,若建立电话的计费,若建立IP_
24、Phone类的对象类的对象my,其调用,其调用为:为: my.charge_Mode();假如假如charge_Mode()是一个类方法,则要使用类名,其调用为:是一个类方法,则要使用类名,其调用为: IP_Phone.charge_Mode(); 例例4.5 8/10/2022第 29 页4.3.3 重载实现多态性v通过重载来实现,它是在通过重载来实现,它是在同一个类同一个类中定义多个同名方法,这中定义多个同名方法,这些方法同名的原因是些方法同名的原因是具有类似的功能且目的相同具有类似的功能且目的相同,但在实现,但在实现该功能的具体方式和细节方面有所不同,因此需要定义多种该功能的具体方式和细
25、节方面有所不同,因此需要定义多种不同的方法体。不同的方法体。 v由于重载发生在同一个类中,不能再用类名或对象名来区分由于重载发生在同一个类中,不能再用类名或对象名来区分不同的方法了,所以在重载中采用的区分方法是使用不同的不同的方法了,所以在重载中采用的区分方法是使用不同的形式参数表,包括形式参数的个数不同、类型不同或顺序的形式参数表,包括形式参数的个数不同、类型不同或顺序的不同。不同。v例如,在重载加法例如,在重载加法add(x,y)时,整数加法的形参类型是整时,整数加法的形参类型是整型,复数加法的形参类型是复数型。根据填入的参数的类型型,复数加法的形参类型是复数型。根据填入的参数的类型或者参
26、量等的不同,系统可以确定调用哪一个加法函数来完或者参量等的不同,系统可以确定调用哪一个加法函数来完成加法计算。成加法计算。 例例4.6 8/10/2022第 30 页4.3.4 多态性举例多态性举例多态性还可以是指在程序中需要使用父类对象的地方,都多态性还可以是指在程序中需要使用父类对象的地方,都可以用子类对象来代替。可以用子类对象来代替。例如:例如:public class Employee extends Objectpublic class Manager extends Employee则:则:Employee e = new Manager(); /合法语句合法语句8/10/2022
27、第 31 页4.3.4 多态性举例多态性举例v 对象状态的确定对象状态的确定在在Java语言中,提供了操作符语言中,提供了操作符instanceof用来判断对象是否用来判断对象是否属于某个类的实例。属于某个类的实例。public void method (Employee e) if ( e instanceof Manager ) /do something as a Manager else if ( e instanceof Contractor ) /do something as a Contractor else /do something else 8/10/2022324.4
28、构造方法的继承与重载8/10/2022第 33 页4.4.1 构造方法的重载v构造方法的重载是指同一个类中定义不同参数的多个构造方构造方法的重载是指同一个类中定义不同参数的多个构造方法,以完成不同情况下对象的初始化。法,以完成不同情况下对象的初始化。例如,例如,point类可定义不同的构造方法创建不同的点对象。类可定义不同的构造方法创建不同的点对象。point();/未初始化坐标未初始化坐标point(x);/初始化一个坐标初始化一个坐标point(x, y);/初始化两个坐标初始化两个坐标一个类的若干个构造方法之间可以相互调用。当类中一个一个类的若干个构造方法之间可以相互调用。当类中一个构造
29、方法需要调用另一个构造方法时,可以使用关键字构造方法需要调用另一个构造方法时,可以使用关键字this,并且这个调用语句应该是该构造方法的第一个可执行语句。并且这个调用语句应该是该构造方法的第一个可执行语句。8/10/2022第 34 页4.4.1 构造方法的重载【例【例4.7】 对对Ordinary_phone类,可以根据需要定义几个构类,可以根据需要定义几个构造方法:造方法:Ordinary_phone( ) /无参数的构造方法,对象的各域置为默认初始值无参数的构造方法,对象的各域置为默认初始值Ordinary_phone(boolean disService) this();/调自身的无参
30、数的构造方法调自身的无参数的构造方法 longdistanceServicedisService; /确定是否开通国内长途电话确定是否开通国内长途电话Ordinary_phone(boolean disService, boolean intService) this(disService);/调自身的带一个参数的构造方法调自身的带一个参数的构造方法 internationalService = intService;/国际长途电话国际长途电话8/10/2022第 35 页4.4.1 构造方法的重载vOrdinary_phone(boolean disService, boolean intS
31、ervice, double b) v /3个参数的构造方法个参数的构造方法v this(disService, intService);v /调自身的带两个参数的构造方法调自身的带两个参数的构造方法v balance =b; /设置话费金额设置话费金额vv使用使用this域来调用同类的其他构造方法,其优点是可以最大域来调用同类的其他构造方法,其优点是可以最大限度地提高对已有代码的利用程度,提高程序的抽象、封装限度地提高对已有代码的利用程度,提高程序的抽象、封装程度,以及减少程序维护的工作量。程度,以及减少程序维护的工作量。8/10/2022第 36 页4.4.2 构造方法的继承v子类可以继承
32、父类的构造方法,构造方法的继承遵循以下原子类可以继承父类的构造方法,构造方法的继承遵循以下原则:则:v(1)子类无条件地继承父类的无参数的构造方法。)子类无条件地继承父类的无参数的构造方法。v(2)如果子类没有定义构造方法,则它将继承父类的无参)如果子类没有定义构造方法,则它将继承父类的无参数构造方法作为自己的构造方法;如果子类定义了构造方法,数构造方法作为自己的构造方法;如果子类定义了构造方法,则在创建新对象时,将先执行继承的父类无参数构造方法,则在创建新对象时,将先执行继承的父类无参数构造方法,然后再执行自己的构造方法。然后再执行自己的构造方法。v(3)对于父类的带参数构造方法,子类可以通
33、过在自己的)对于父类的带参数构造方法,子类可以通过在自己的构造方法中使用构造方法中使用supper关键字来调用它,但这个调用语句必关键字来调用它,但这个调用语句必须是子类构造方法的第一个可执行语句。须是子类构造方法的第一个可执行语句。v下面我们主要讨论第下面我们主要讨论第2和第和第3点。点。8/10/2022第 37 页4.4.2 构造方法的继承v1. 父类与子类的构造方法的执行顺序父类与子类的构造方法的执行顺序下面给出一个简单示意性的例子。下面给出一个简单示意性的例子。【例【例4.6】 试分析下面程序的继承关系以及构造试分析下面程序的继承关系以及构造方法的调用顺序。我们是否可以先不看执行结果
34、,方法的调用顺序。我们是否可以先不看执行结果,分析构造方法执行顺序是分析构造方法执行顺序是A()、B()、C()还是还是C()、B()、A()?例例4.68/10/2022第 38 页4.4.2 构造方法的继承v2. 在构造方法中在构造方法中super关键字的使用关键字的使用super是表示父类对象的关键字,是表示父类对象的关键字,super表示当前对象的直表示当前对象的直接父类,代表了当前父类对象的一个引用,其作用是利用接父类,代表了当前父类对象的一个引用,其作用是利用super可使用父类对象的方法或域。可使用父类对象的方法或域。Fixed_Telephone( ) /无参数的构造方法无参数
35、的构造方法Fixed_Telephone (long pn) phoneNumber = pn; /初始化电话号码初始化电话号码Fixed_ Telephone (long pn, double mf ) phoneNumber = pn; monthFee = mf; /初始化座机费初始化座机费Fixed_Telephone(long pn, double mf, double b) phoneNumber = pn; monthFee = mf; balance= b;/初始化电话费的剩余金额初始化电话费的剩余金额8/10/2022第 39 页4.4.2 构造方法的继承设计子类的构造方法可
36、选择如下方式:设计子类的构造方法可选择如下方式:(1)仅调用父类的无参数构造方法。)仅调用父类的无参数构造方法。(2)定义自己的一个(或多个)构造方法并调用父类的带参)定义自己的一个(或多个)构造方法并调用父类的带参数的构造方法。数的构造方法。 Fixed_Telephone( ) /无参数的构造方法无参数的构造方法Fixed_Telephone (long pn) phoneNumber = pn; /初始化电话号码初始化电话号码Fixed_ Telephone (long pn, double mf ) phoneNumber = pn; monthFee = mf; /初始化座机费初始化
37、座机费Fixed_Telephone(long pn, double mf, double b) phoneNumber = pn; monthFee = mf; balance= b;/初始化电话费的剩余金额初始化电话费的剩余金额Ordinary_phone (long pn , double mf , boolean ds) super (pn, mf); longdistanceService = ds; Ordinary_phone(long pn , double mf , double b , boolean ds) super (pn ,mf, b);/调用父类三调用父类三个参数
38、的构造方法为继承的域赋初值个参数的构造方法为继承的域赋初值 longdistanceService = ds ;/用参数初始化自定用参数初始化自定义域义域8/10/2022第 40 页4.4.3 构造方法的综合举例综合举例构造方法的继承与重载以及方法的覆盖的综合举例。构造方法的继承与重载以及方法的覆盖的综合举例。 【例【例4.8】 本例中使用重载技术定义了本例中使用重载技术定义了Fixed_PhoneCsrd类的类的4个构造方个构造方法;使用继承和重载技术定义了法;使用继承和重载技术定义了Ordinary_phone类的两个构类的两个构造方法;使用覆盖技术在造方法;使用覆盖技术在Ordinar
39、y_phone类中覆盖了父类的类中覆盖了父类的getBalance()方法以及方法以及Object类的类的toString()方法。主类中创方法。主类中创建类的对象建类的对象myHomePhone时使用了第二个构造方法,并对时使用了第二个构造方法,并对大部分的域都进行初始化,大部分的域都进行初始化, 8/10/2022414.5 接 口8/10/2022第 42 页v接口(接口(interface)也有人翻译为界面,是用来实现类间多重)也有人翻译为界面,是用来实现类间多重继承功能的一种结构。继承功能的一种结构。v接口是在语法上与类有些相似。它定义了若干个抽象方法和接口是在语法上与类有些相似。它
40、定义了若干个抽象方法和常量,形成一个属性集合,该属性集合通常对应了某一组功常量,形成一个属性集合,该属性集合通常对应了某一组功能。能。v凡是需要实现这种特定功能的类,都可以继承并使用它。一凡是需要实现这种特定功能的类,都可以继承并使用它。一个类只能直接继承一个父类,但可以同时实现若干个接口。个类只能直接继承一个父类,但可以同时实现若干个接口。实现(或继承)接口实际上就获得了多个特殊父类的属性,实现(或继承)接口实际上就获得了多个特殊父类的属性,即实现了多重继承。即实现了多重继承。v接口定义的仅是实现某特定功能的一组对外接口和规范,而接口定义的仅是实现某特定功能的一组对外接口和规范,而这个功能的
41、真正实现是在继承这个接口的各类中完成的。这个功能的真正实现是在继承这个接口的各类中完成的。8/10/2022第 43 页4.5.1 4.5.1 接口与多继承接口与多继承所谓多重继承,是指一个子类可以有一个以上的直接父类,所谓多重继承,是指一个子类可以有一个以上的直接父类,该子类可以继承它所有的直接父类的属性。该子类可以继承它所有的直接父类的属性。 接口定义的仅仅是实现某一特定功能的一组对外的协议和规接口定义的仅仅是实现某一特定功能的一组对外的协议和规范,而并没有真正地实现这个功能。这些功能的真正实现是范,而并没有真正地实现这个功能。这些功能的真正实现是在继承这个接口的各个类中完成的。在继承这个
42、接口的各个类中完成的。因为接口包含的是未实现的一些抽象的方法,它与抽象类有因为接口包含的是未实现的一些抽象的方法,它与抽象类有些相象。研究一下接口与抽象类到底有什么区别是很有意义些相象。研究一下接口与抽象类到底有什么区别是很有意义的。它们之间存在以下的区别:的。它们之间存在以下的区别: 接口不能有任何实现了的方法,而抽象类可以。接口不能有任何实现了的方法,而抽象类可以。 类可以继承(实现)许多接口,但只能继承一个父类。类可以继承(实现)许多接口,但只能继承一个父类。 类有严格的层次结构,而接口没有层次结构,没有联系的类类有严格的层次结构,而接口没有层次结构,没有联系的类可以实现相同的接口。可以
43、实现相同的接口。 8/10/2022第 44 页4.5.2 接口的定义v接口是由常量和抽象方法组成的特殊类。接口的定义包括两个部分:接口声明和接口体。声明接口一般格式如下:vpublic interface 接口名 extends 父接口名表 v 域类型 域名常量值;/常量域声明v 返回类型 方法名(参数表);/抽象方法声明vv接口声明中有两个部分是必需的:interface关键字和接口的名字。用public修饰的接口是公共接口,可以被所有的类和接口使用;没有public修饰符的接口则只能被同一个包中的其他类和接口利用。8/10/2022第 45 页4.5.3 接口的实现为了使用接口,要编写实
44、现接口的类。实现某一个接口,在类的声为了使用接口,要编写实现接口的类。实现某一个接口,在类的声明中要包括一条明中要包括一条implements语句。一个类可以实现多个接口,可以语句。一个类可以实现多个接口,可以在在implements后面列出要实现的多个接口,这些接口以逗号分隔。后面列出要实现的多个接口,这些接口以逗号分隔。一个类实现某个接口,那么这个类就应提供在接口中定义的所有抽一个类实现某个接口,那么这个类就应提供在接口中定义的所有抽象方法的具体实现。象方法的具体实现。 public class StockApplet extends Applet implements StockWatc
45、her public void valueChanged(String tickerSymbol, double newValue) if (tickerSymbol.equals(sunTicker) else if (tickerSymbol.equals(oracleTicker) 8/10/2022第 46 页interface Collection int MAX_NUM=100;void add(Object obj);void delete(Object obj);Object find(Object obj);int currentCount( );class FIFOQueu
46、e implements Collection void add ( Object obj ) void delete( Object obj ) Object find( Object obj ) int currentCount() 4.5.3 接口的实现8/10/2022第 47 页v实现接口时应注意的问题:实现接口时应注意的问题:(1)在类的声明部分,用)在类的声明部分,用implements关键字声明该类将要实关键字声明该类将要实现哪些接口。现哪些接口。(2)类在实现抽象方法时,必须用)类在实现抽象方法时,必须用public修饰符。修饰符。(3)除抽象类以外,在类的定义部分必须为接口
47、中所有的抽)除抽象类以外,在类的定义部分必须为接口中所有的抽象方法定义方法体,且方法首部应该与接口中的定义完全一象方法定义方法体,且方法首部应该与接口中的定义完全一致。致。(4)若实现某接口的类是)若实现某接口的类是abstract的抽象类,则它可以不实的抽象类,则它可以不实现该接口所有的方法。但是对于这个抽象类的任何一个非抽现该接口所有的方法。但是对于这个抽象类的任何一个非抽象子类,不允许存在未被实现的接口方法。即非抽象类中不象子类,不允许存在未被实现的接口方法。即非抽象类中不能存在抽象方法。能存在抽象方法。4.5.3 接口的实现8/10/2022第 48 页4.5.4 接口的使用 如果一个
48、接口需要扩充,可以创建新的接口来继承老接口。如果一个接口需要扩充,可以创建新的接口来继承老接口。比如,可以比如,可以StockWatcher接口需要增加一个方法,则可以创建接口需要增加一个方法,则可以创建一个子接口一个子接口StockTracker: public interface StockTracker extends StockWatcher void currentValue(String tickerSymbol,double newValue); 接口除了被继承和实现之外,还可以作为一种类型来使用接口除了被继承和实现之外,还可以作为一种类型来使用当定义一个新的接口的时候,实际上是
49、定义了一个新的引用数当定义一个新的接口的时候,实际上是定义了一个新的引用数据类型。在可以使用其他类型的名字(如变量声明、方法参数据类型。在可以使用其他类型的名字(如变量声明、方法参数等)的地方,都可使用这个接口名。等)的地方,都可使用这个接口名。 例如,在例如,在StockMonitor类中的类中的watchStock()方法中的第一个方法中的第一个参数的数据类型为参数的数据类型为StockWatcher接口。只有实现接口。只有实现StockWatcher接口的类对象可以替代接口的类对象可以替代watcher形参。形参。 哲学家哲学家8/10/2022494.6 抽象类、接口和Object类的
50、应用8/10/2022第 50 页v假设有若干假设有若干 (如如1000)个)个Circle,Rectangle以及若干个其他以及若干个其他形状,希望计算它们的总面积,直截了当的做法是将它们分形状,希望计算它们的总面积,直截了当的做法是将它们分别放到多个数组中,分别循环求出各形状的面积,然后累加,别放到多个数组中,分别循环求出各形状的面积,然后累加,这种做法是不漂亮的。这种做法是不漂亮的。v如果还有其它形状:如果还有其它形状:triangle,ellipses等,上述方法显得等,上述方法显得“累赘累赘”。我们希望有一种统一的表示,例如用一个数组。我们希望有一种统一的表示,例如用一个数组shap