第4章 Java面向对象编程(下

整理文档很辛苦,赏杯茶钱您下走!

免费阅读已结束,点击下载阅读编辑剩下 ...

阅读已结束,您可以下载文档离线阅读编辑

资源描述

Java实用教程(第3版)第4章Java面向对象编程(下)4.1继承4.2对象的转型4.3多态4.4抽象类4.5接口4.6终止继承4.7权限修饰符4.8综合实例:航班管理Java实用教程(第3版)4.1继承4.1.1继承的定义在Java语言中,用extends关键字来声明一个类继承了另一个类,其语法格式是:修饰符class子类名extends父类{…}例如,下面的代码片段定义了一个子类son类,继承了父类farther类:classfather{…}publicclasssonextendsfather{…}Java实用教程(第3版)4.1.1继承的定义注意,Java只支持单继承,例如,下面的son类试图继承两个类:classgrandFather{…}classfarther{…}publicclasssonextendsfarther,grandFather{//错误,不允许继承两个类…}【例4.1】计算箱子的体积和重量。Java实用教程(第3版)4.1.2初始化基类当创建一个子类的对象时,该对象包含了一个基类对象。这个基类对象与用子类直接创建的对象是一样的。二者的区别在于,后者来自于外部,而基类对象被包装在子类对象内部。Java虚拟机会确保在子类构造器中调用基类的构造器来初始化基类。【例4.2】子类构造器C调用基类的构造器A来初始化基类。Java实用教程(第3版)4.1.3方法的重写子类通过extends关键字声明继承了父类的属性和方法,但子类可能觉得从父类继承过来的方法不能满足自己的要求,怎么办呢?解决方法是子类可以重写(或覆盖)父类的方法。例如在下面的代码片段中,子类重写了父类的run()方法:classAnimal{…voidrun(){//慢跑}}classTigerextendsAnimal{…voidrun(){//快跑}}【例4.3】子类Employee重写父类的getInfo()方法。Java实用教程(第3版)4.1.3方法的重写在使用方法重写时,以下几点需要注意。(1)子类重写的方法必须与父类被重写的方法具有相同的方法名称、参数列表和相同或相容的返回值类型,否则不构成重写。如:父类定义了方法:intf(inti){…}。若子类方法重写时写成:bytef(inti){…},由于返回值类型是Java基本数据类型,必须要相同。因而编译程序会报错。但是,若父类定义了方法:Objectget(){…},子类方法重写时写成Pointget(){…},虽然返回值类型不同,但由于Point是Object的子类,因而是允许的。即对于返回值类型是引用,则要求相容。这种方式的重写很有用。Java实用教程(第3版)4.1.3方法的重写(2)子类重写的方法不能比父类中被重写的方法拥有更严格的访问权限。例如,在下面的代码片段中,子类试图缩小父类方法的访问权限:classBase{...publicvoidmethod(){...}}publicclassSubextendsBase{...privatevoidmethod(){//编译错误,子类方法缩小父类方法的访问权限...}}Java实用教程(第3版)4.1.3方法的重写(3)父类的静态方法不能被子类重写为非静态的方法。同样,父类中的实例方法也不能被子类重写为静态方法。例如下面的代码片段:classBase{...staticvoidmethod(){...}}publicclassSubextendsBase{...voidmethod(){//编译错误...}}Java实用教程(第3版)4.1.3方法的重写(4)方法重写只针对实例方法,父类中的静态方法,子类只能隐藏、重载和继承。(5)父类中能被子类继承的实例方法,才会在子类中被重写。(6)子类重写的方法不能比父类中被重写的方法声明抛出更多的异常。方法重写和方法重载具有以下相同点:都要求方法同名。都可以用于抽象方法和非抽象方法之间。方法重写和方法重载具有以下不同点:方法重写要求参数签名必须一致,而方法重载要求参数签名必须不一致。方法重写要求返回类型必须一致,而方法重载对此不做限制。方法重写只能用于子类从父类继承的实例方法,方法重载用于同一个类的所有方法(包括从父类中继承而来的方法)。方法重写对方法的访问权限和抛出的异常有特殊的要求,而方法重载在这方面没任何限制。父类的一个方法只能被子类重写一次,而一个方法在所在的类中可以被重载多次。构造方法能被重载,但不能被重写。Java实用教程(第3版)4.1.4super关键字若子类重写了父类中的方法或子类隐藏了父类中的数据成员,但又想访问父类的成员变量和方法,怎么办?解决的办法是使用super关键字。【例4.4】子类SubClass使用super关键字,访问父类SuperClass的成员变量和构造方法。Java实用教程(第3版)4.2对象的转型例如,B类是A类的子类或间接子类,当子类B创建一个对象,并把这个对象赋给类A的引用变量,那么,称这个A类对象a是子类对象b的向上转型的对象。这个向上转型的对象还可以通过强制类型转换还原成它本来的类型,被称为对象的向下转型。classA{}classBextendsA{}Aa;Bb1=newB();a=b1;//向上转型Bb2=(B)a;//向下转型向上转型的对象具有如下特点:(1)向上转型对象不能操作子类新增的成员属性和方法(失掉了这部分功能)。(2)向上转型对象可以操作子类继承或隐藏的成员变量,也可以使用子类继承的或重写的方法。(3)向上转型对象操作子类继承或重写的方法时,就是通知对应的子类对象去调用这些方法。因此,如果子类重写了父类的某个方法后,对象的向上转型对象调用这个方法时,一定是调用了这个重写的方法。(4)可以将向上转型对象再强制转换到它本来的类型,该对象又具备了其所有属性和方法。【例4.5】测试对象转型的特点,使用instanceof判断一个实例对象是否属于某个类。Java实用教程(第3版)4.2对象的instanceof可以判断一个引用变量所指向的对象是否属于某个类,所以在执行下面第一条语句返回true,执行第二条语句发生了对象的向上转型,Person类的引用变量指向System.out.println(pinstanceofEmployee);p=newEmployee(Mary,3000);Employee对象,如图4.1的箭头①。但这时引用变量p所能访问的内容只限于Employee对象的父类Person对象,也就是箭头②所指向的区域。在执行下面的这条语句时,发生了对象的向下转型。Employeee1=(Employee)p;Employee类的引用变量e1同样指向Employee对象。这时引用变量e1能访问Employee对象的所有内容,也就是箭头③所指向的区域。Person:pname:Marysalary:3000Employee对象Person对象堆内存①②Employee:e1③栈内存图4.1程序执行的内存布局Java实用教程(第3版)4.2对象的程序运行结果:truetruetruefalseMarytruetrue3000Iamworkinghard!Lily4000Iamstudyinghard!nameis:LilystudentIdis:4000nameis:JohnstudentIdis:18nameis:LucystudentIdis:2000Java实用教程(第3版)4.3多态运行Cast.java程序,可以发现testCase()方法接受一个Person引用。那么在这种情况下,编译器怎样才能知道这个Person引用指向的是Student对象还是Employee对象?实际上,编译器无法得知,解决的方法就是动态绑定。它的含义就是在运行期间(而非编译期间)判断所引用对象的实际类型并根据对象的类型进行绑定,从而调用恰当的方法。只要满足类之间有继承关系、子类重写父类的方法、父类引用指向子类对象这三个条件,动态绑定就会自动发生,从而实现多态。多态不但能够改善代码的组织结构和可读性,还能够创建可扩展的程序,消除类型之间的耦合关系。多态方法调用允许一种类型表现出与其他相似类型之间的区别,只要它们都是继承同一基类。【例4.6】Polymorphism程序满足多态条件,根据对象的类型调用恰当的方法。Java实用教程(第3版)4.4抽象类在Java中,只声明而没有实现的方法称为抽象方法,其语法规则如下:abstract返回值类型抽象方法名([形式参数列表]);用abstract修饰的类称为抽象类,其语法规则如下:[访问修饰符]abstractclass类名{…}下面的Graphix类定义为抽象类,方法calArea()定义为抽象方法:abstractclassGraphix{//抽象类abstractvoidcalArea();//抽象方法}classRectextendsGraphix{voidcalArea(){//重写抽象方法System.out.println(计算长方形面积);}}Java实用教程(第3版)4.4抽象类抽象类具有以下特性:(1)含有抽象方法的类必须被声明为抽象类,抽象类必须被继承,抽象方法必须被实现。(2)抽象类中不是所有的方法都是抽象方法,可以在抽象类中声明并实现方法。(3)抽象类的子类必须实现父类的所有抽象方法后才能实例化,否则这个子类也成为一个抽象类。(4)抽象类不能实例化。【例4.7】Dog类继承Animal类并实现抽象方法run()。Java实用教程(第3版)4.5接口接口的定义格式如下:[public]interface接口名[extends一系列父接口]{常量或抽象方法的集合}关键字interface用于定义接口,接口通常都定义为public类型。例如,定义一个接口:publicinterfaceRunner{intid=1;//等价于publicstaticfinalintid=1;publicvoidstart();//等价于publicabstractvoidstart();publicvoidrun();publicvoidstop();}Java实用教程(第3版)4.5接口接口具有以下特性:(1)接口中的常量默认为publicstaticfinal,并且也只能是publicstaticfinal。(2)接口中只能定义抽象方法,而且这些方法默认为publicabstract,并且也只能是publicabstract类型。(3)接口可以继承其他的接口,并添加新的属性和抽象方法。(4)在接口中声明方法时,不能使用native、static、final、synchronized、private、protected等修饰符。(5)Java中不允许类的多继承,但允许接口的多继承。(6)不允许创建接口的实例,但允许定义接口类型的引用变量,该变量引用实现了该接口的类的实例。(7)一个类只能继承另外一个类,但能同时实现多个接口,并且重写的方法必须显式声明为public。【例4.8】测试接口的多种特性。Java实用教程(第3版)4.6终止继承final具有“不可改变”的含义,它可以修饰非抽象类、非抽象成员方法和变量。(1)用final修饰的类不能被继承,没有子类。(2)用final修饰的方法不能被子类的方法重写或隐藏。(3)用final修饰的变量表示常量,只能被赋值一次。(4)父类中用private修饰的方法不能被子类的方法重写,因此private类型的方法默认是final类型的。Java实用教程(第3版)4.6.1final类继承关系的弱点是打破封装,子类能够访问父类的实现细节,而且能以方法重写的方式改变实现细节。在以下情况下。可以考虑把类设计为final类型,使得这个类不能被继承。(1)不是专门为继承而设计的类,类本身的方法之间有复杂的调用关系。如果随意创建这些类的子类,子类有可能错误地修改父类的

1 / 38
下载文档,编辑使用

©2015-2020 m.777doc.com 三七文档.

备案号:鲁ICP备2024069028号-1 客服联系 QQ:2149211541

×
保存成功