六章节深入面向对象程序设计.ppt

上传人:本田雅阁 文档编号:3186286 上传时间:2019-07-22 格式:PPT 页数:142 大小:470.04KB
返回 下载 相关 举报
六章节深入面向对象程序设计.ppt_第1页
第1页 / 共142页
六章节深入面向对象程序设计.ppt_第2页
第2页 / 共142页
六章节深入面向对象程序设计.ppt_第3页
第3页 / 共142页
六章节深入面向对象程序设计.ppt_第4页
第4页 / 共142页
六章节深入面向对象程序设计.ppt_第5页
第5页 / 共142页
点击查看更多>>
资源描述

《六章节深入面向对象程序设计.ppt》由会员分享,可在线阅读,更多相关《六章节深入面向对象程序设计.ppt(142页珍藏版)》请在三一文库上搜索。

1、第六章 深入面向对象的程序设计,6.1 继承与重载 6.1.1 继承关系的定义 Java中的继承是通过extends关键字来实现的,在定义类时使用extends关键字指明 新定义类的父类,就在两个类之间建立了继承关系。 新定义的类称为子类,它可以从父类那里继承所有的非private的属性和方法作为自己的成员。 见例类Employee、CommonEmployee、ManagerEmployee,6.1.2 属性的继承与隐藏,1.属性的继承 子类可以继承父类非私有的所有属性。仍以前例来说,我们把它的所有属性略加修改后重列在下面: class Employee /定义父类:雇员类 int m_Em

2、pNo; /雇员编号 String m_EmpName; /雇员姓名 char m_EmpGender; /雇员性别 double m_EmpSalary; /雇员工资 Date m_StartWorkDate; /开始工作日期 static final double m_MinSalary=250; /静态常量属性:最低工资 static int m_NextEmpNo; ,CommonEmployee类的所有属性包括: int m_EmpNo; /雇员编号 String m_EmpName; /雇员姓名 char m_EmpGender; /雇员性别 double m_EmpSalary;

3、 /雇员工资 Date m_StartWorkDate; /开始工作日期 static final double m_MinSalary=250; /静态常量属性:最低工资 static int m_NextEmpNo; /以上为继承自父类的成员变量 double m_EmpBonus;/子类的自定义属性:内部奖金,ManagerEmployee类的所有属性包括: int m_EmpNo; /雇员编号 String m_EmpName; /雇员姓名 char m_EmpGender; /雇员性别 double m_EmpSalary; /雇员工资 Date m_StartWorkDate; /

4、开始工作日期 static final double m_MinSalary=250; /静态常量属性:最低工资 static int m_NextEmpNo; /以上为继承自父类的成员变量 Date m_WorkAsManager; /子类自定义属性:开始任主管现职的日期,说明: 父类的所有非私有属性实际是各子类都拥有的属性的集合。 子类从父类继承属性不需要把父类属性的定义部分再复制一遍。 优点:减少程序的维护量。,2.属性的隐藏,子类从父类继承来的属性变量重新加以定义,称为属性的隐藏。 见例6.1 TestHide.java,6.1.3 方法的继承、重载和覆盖,1.方法的继承 父类的非私有

5、方法作为类的私有成员,也可以被子类所继承。 见例6.2 InheritMethod.java,2.方法的覆盖,在子类中定义与父类相同的方法,称为方法的覆盖。 见例6.3 OverrideMethod.java 注: 在方法的覆盖中,由于同名方法隶属于不同的类,所以要解决调用如何区分它们的问题,只需要在方法名前面使用不同的类名或不同类的对象名即可。 子类在重新定义父类已有的方法时,应保持与父类完全相同的方法头声明,即应与父类有完全相同的方法名、返回值和参数列表。,3.方法的重载,子类定义同名方法来覆盖父类的方法是面向对象方法中多态技术的一种实现。 所谓多态是指同名的不同方法共存。有助于隐藏对象内

6、部的细节,提高程序的抽象程序,是面向对象程序设计中经常使用的方法。 实现多态技术的另一种重要的手段就是方法的重载。 重载与覆盖不同,重载不是子类对父类同名方法的重新定义,而是类对自身已有的同名方法的重新定义。,方法的重载是同类中同名方法共存的情况,不能像方法的覆盖那样采用类名前缀来区分,而应该采用通过参数列表来区分不同的方法。 同类中同名的不同方法需要有不同的参数列表,包括参数顺序的不同和参数类型的不同。,6.1.4 父类对象与子类对象的使用与转化,This和super是常用来指代父类对象和子类对象的关键字。 Java系统默认,每个类都缺省地具有null、this和super三个量,所以在任意

7、类中都可以不加说明而直接使用它们。 Null代表“空”,代表一个什么也没有的“空”值,一般用null来代表尚未存在的对象,在定义一个对象但尚未为其开辟内存单元时可以指定这个对象为null。,1.this,this表示的是当前对象本身 更准确地说,this代表了当前对象的一个引用。 对象的引用可以理解为对象的另一个名字,通过引用可以顺利地访问到对象,包括修改对象的属性、调用对象的方法。 boolean addSalYearly() if (workDays()=365) this.setEmpSalary(getEmpSalary()*1.2); return true; else return

8、 false; ,This通常用来把当前对象的引用作为参数传递给其他的对象或方法。如: class SecretaryEmployee extends CommonEmployee /一般雇员的子类:秘书类 SecretaryEmployee(ManagerEmployee boss) /秘书的构造函数 m_EmpSalary=boss.getSalary()/3; /秘书的薪金是上司的三分之一 m_StartWorkDate=new Date(boss.m_WorkAsManager(); /与上司同时开始工作 ,class ManagerEmployee extends Employee

9、/雇员的子类2:主管 SecretaryEmployee m_Secretary; /主管的秘书 Date m_WorkAsManager; /开始任主管现职的日期 private double m_HoldStock; /主管持有的公司股票额 static double m_MinSalary=800; ManagerEmployee(Date mgrdate) /主管的构造函数 m_WorkAsManager=new Date(mgrdate.getTime(); /初始化开始任主管日期 m_Secretary=new SecretaryEmployee(this); /每新任命一位主管,

10、都为他指派一名秘书 说明:每新建一个ManagerEmployee对象时,都同时创建一个SecretaryEmployee对象作为其秘书。,2.super,Super表示的是当前对象的直接父类对象,是当前对象的直接父类对象的引用。 所谓直接父类是相对于当前对象的其他“祖先”类而言。,public void paint(Graphics g) g.drawString(“调用父类的方法访问父类的最低工资:“+super.getMinSalary(),20,20); g.drawString(“直接访问子类的最低工资:+MgrEmp. m_MinSalary,20,40); g.drawStrin

11、g(“调用子类的方法访问子类的最低工资“+MgrEmp.getMinSalary(),20,60); ,注意: this和super是属于类的所有特指的属性(即类的成员),只能用来代表当前对象和当前对象的父对象,而不能像其他类的属性一样随意引用。下列都是错误的代码: ManagerEmployee MgrEmp=new ManagerEmployee(); MgrEmp.this.getMinSalary();/Error MgrEmp.super.workDays();/Error,3.父类对象与子类对象的转换,父类对象和子类对象的转化需要注意如下的原则: 子类对象可以被视为是其父类的一个对

12、象; 父类对象不能被当作是其某一个子类的对象; 如果一个方法的形式参数定义的是父类对象,那么调用这个方法时,可以使用子类对象作为实际参数; 如果父类对象引用指向的实际是一个子类对象,那么这个父类对象的引用可以用强制类型转换成子类对象的引用。,例: class superClass /定义父类 int x; . class SubClass extends SuperClass /定义子类 int y; char ch; . ,public class UseSuperSub /使用父类与子类 SuperClass sc,sc_ref; SubClass sb,sb_ref; sc=new Su

13、perClass(); sb=new SubClass(); sc_ref=sb; /父类引用可以指向子类对象 sb_ref=(SubClass)sc_ref; /父类引用转换成子类引用 ,6.1.5 构造函数的继承与重载,构造函数是类的一种特殊函数,它也可以从父类那里继承,也可以互相重载。 1.构造函数的重载 构造函数的重载是指同一个类中存在着若干个具有不同参数列表的构造函数。 当一个类因构造函数的重载而存在着若干个构造函数时,创建该类对象的语句会自动根据给出的实际参数的数目、类型和顺序来确定调用哪个构造函数来完成新对象的初始化工作。,一个类的若干构造函数之间可以相互调用。 Employee

14、() m_EmpNo=m_NextEmpNo+; Employee(String name) m_EmpNo=m_NextEmpNo+; m_EmpName=new String(name); Employee(String name,double initSal) m_EmpNo=m_NextEmpNo+; m_EmpName=new String(name); if (initSalm_MinSalary) System.exit(0); m_EmpSalary=initSal; ,Employee(String name,double initSal,char sex) m_EmpNo=

15、m_NextEmpNo+; m_EmpName=new String(name); if (initSalm_MinSalary) System.exit(0); m_EmpSalary=initSal; m_EmpGender=sex; Employee(String name,double initSal,char sex,Date wdate) m_EmpNo=m_NextEmpNo+; m_EmpName=new String(name); if (initSalm_MinSalary) System.exit(0); m_EmpSalary=initSal; m_EmpGender=

16、sex; m_StartWorkDate=new Date(wdate.getTime(); ,当一个构造函数需要调用另一个构造函数时,应使用关键字this,同时这个调用语句应该是整个构造函数的第一个可执行语句。如: Employee() m_EmpNo=m_NextEmpNo+; Employee(String name) this(); m_EmpName=new String(name); ,Employee(String name,double initSal) this(name); if (initSalm_MinSalary) System.exit(0); m_EmpSalar

17、y=initSal; Employee(String name,double initSal,char sex) this(name,initSal); m_EmpGender=sex; Employee(String name,double initSal,char sex,Date wdate) this(name,initSal,sex); m_StartWorkDate=new Date(wdate.getTime(); ,2.构造函数的继承,子类可以继承父类的构造函数,构造函数的继承遵循以下的原则: 子类无条件地继承父类的不含参数的构造函数; 如果子类自己没有构造函数,则它将继承父类

18、的无参数构造函数作为自己的构造函数;如果子类自己定义了构造函数,则它在创建新对象时,它将先执行继承自父类的无参数构造函数,然后再执行自己的构造函数; 对于父类的含参数构造函数,子类可以通过在自己构造函数中使用super关键字来调用它,但这个调用语句必须是子类构造函数的第一个可执行语句。,例:假设父类Employee有上述的五个构造函数,子类ManagerEmployee的构造函数可以有如下的几种设计方法: ManagerEmployee不专门定义自己的构造函数 在这种情况下,每当创建主管对象时,系统自动调用的实际是父类Employee的无参数构造函数,这个构造函数将为新对象设置雇员编号,相应的

19、语句是: MangerEmployee Mgr=ManagerEmployee();,ManagerEmployee定义自己的构造函数并调用父类的含参数构造函数,在父类构造函数的初始化操作的基础上定义子类自己的初始化操作: ManagerEmployee(String name,double initSal,char sex,Date wdate,Date mdate) super(name,initSal,sex,wdate); m_WorkAsManager=new Date(mdate.getTime(); ,在ManagerEmployee类实现构造函数的重载,满足多层次的对象初始化需

20、要: ManagerEmployee(String name,Date mdate) super(name); m_WorkAsManger=new Date(mdate.getTime(); MangerEmployee(Stringname,double initSal,char sex,Date mdate) super(name,initSal,sex,wdate); m_WorkAsManager=new Date(mdate.getTime); ,6.2 包(package),Java中的包把各种类组织在一起,使得程序功能清楚、结构分明。 使用包有利于实现不同程序间类的复用。 包是

21、一种松散的类的集合,一般不要求处于同一个包中的类有明确的相互关系,如包含、继承等,但是由于同一包中的类在缺省情况下可以互相访问,所以为了方便编程和管理,通常把需要在一起工作的类放在一个包里。,1.创建包,缺省情况下,系统会为每一个.java源文件创建一个无名包,该.java文件中定义的所有类都隶属于这个无名包,它们之间可以相互引用。 但是由于这个无名包是没有名字的,所以它不能被其他包所引用,即无名包中的类不能被其他包中的类所利用和复用。,创建包的语句需要用关键字package,而且是整个.java文件的第一个语句。 格式: package 包名; 例:package EmpClasses; p

22、ackage EmpSystem.EmpClasses;/创建两个子文件夹 注:实际上,创建包就是在当前文件夹下创建一个子文件夹,以便存放这个包中包含的所有类的.class文件。,2.包的引用,将类组织成包的目的是为了更好地利用包中的类。 引用不在同一个包中的其它非public类,可以使用下面几种方法: (1)使用包名、类名前缀 一个类要引用其他的类,无非是创建这个类的对象并使用它的属性或调用它的方法。 对于同一个包中的其他类,只需在要使用的属性或方法名前加上类名作为前缀即可; 对于其他包中的类,则需要在类名前缀的前面加上包名前缀。,(2)加载需要使用的类,在程序的开始部分利用import语句

23、将需要使用的整个类加载到当前程序中,这样在程序中需要引用这个类的地方就不需要再使用包名作为前缀即可。,(3)加载其他包,可以直接利用import语句引入整个包。 Import java.awt.*;,(4)CLASSPATH,环境变量CLASSPATH类似于DOS操作系统中的PATH,它指明了所有缺省的类字节码文件路径。当一个程序找不到它所需使用的其他类的.class文件时,系统会自动到CLASSPATH环境变量所指明的路径中去寻找。,6.3 接口,接口在有些资料上被称为界面,英文名称为interface。 接口与包相似,也是用来组织应用中的各类并调节它们的相互关系的一种结构。 接口是用来实现

24、类间多重继承功能的结构。,6.3.1 接口的基本概念,Java中的接口在语法上相似于类,定义了若干的抽象方法和常量,形成一个属性集合,该属性集合通常代表了某一组功能的实现,其主要作用是可以帮助我们实现类似于类的多重继承的功能。 多重继承是指一个子类可以有一个以上的直接父类,该子类可以继承它所有直接父类的成员。,说明: Java中的接口中的属性都是常量,接口中的方法都是没有方法体的抽象方法。 接口定义的仅仅是实现某一特定功能的一组功能的对外接口和规范。 接口并没有真正地实现这个功能,这个功能的真正实现是在“继承”了这个接口的各个类中完成的,由这些类来具体定义接口中各抽象方法的方法体。 因此,在J

25、ava中,通常把对接口功能的“继承”称为“实现”。,6.3.2 接口的声明,Java中声明接口的语法如下: public interface 接口名 extends 父接口名列表 /接口体 /常量域声明 publicstaticfinal域类型 域名常量值; /抽象方法声明 publicabstracenative返回值 方法名(参数列表)throw 异常列表; ,接口实际上就是一种特殊的类; 接口是由常量和抽象方法组成的特殊类。 一个类只能有一个父类,但是可以同时实现若干个接口。 用public修饰的接口是公共接口,可以被所有的类和接口使用,而没有public修饰符的接口则只能被同一个包中的

26、其他类和接口利用。,接口也具有继承性。定义一个接口时可以通过extends关键字声明该新接口是某个已经存在的父接口的派生接口,它将继承父接口的所有属性和方法。 一个接口可以有一个以上的父接口,它们之间用逗号分隔,形成父接口列表。新接口将继承所有父接口中的属性和方法。,接口体的声明是定义接口的重要部分,接口体由两部分组成,一部分是对接口中属性的声明,另一部分是对接口中方法的声明。 属性都是用final修饰的常量 方法都是用abstract修饰的抽象方法,在接口中只能给出这些抽象方法的方法名、返回值和参数列表,而不能定义方法体。,接口中的所有属性都必须是public static final,这是

27、系统默认的规定,所以接口属性也可以没有任何修饰符,其效果完成相同。 同样,接口中的所有方法都必须是默认的public abstract,无论是否有修饰符显示地限定它。,例: public interface Awardable final double m_MaxAwardRate=0.1; /最高提成比例 final double m_MinAwardRate=0.002; /最低提成比例 abstract double getAwardRate(); /获得提成比例 abstract boolean setAwardRate(double newrate); /设置提成比例 abstrac

28、t void caculateAward(); /计算提成数额 abstract double getAward(); /获取提成数额 ,6.3.3 接口的实现,一个类要实现某个或某几个接口时,有如下的步骤和注意事项: (1)在类的声明部分,用implements关键字声明该类将要实现哪些接口; (2)如果实现某接口的类不是abstract的抽象类,则在类的定义部分必须实现指定接口的所有抽象方法,即为所有抽象方法定义方法体,而且方法头部分应该与接口中的定义完全一致,即有完全相同的返回值和参数列表; (3)若实现某接口的类是abstract的抽象类,则它可以不实现该接口所有的方法。但是对于这个抽

29、象类任何一个非抽象的子类而言,它们父类所实现的接口中的所有抽象方法都必须有实在的方法体,这些方法体可以来自抽象的父类,也可以来自子类自身,但是不允许存在未被实现的接口方法。主要体现了非抽象类中不能存在抽象方法的原则。 (4)一个类在实现某接口的抽象方法时,必须使用完全相同的方法头。 (5)接口的抽象方法,其访问限制符都已指定是public,所以类在实现方法时,必须显示地使用public修饰符。,6.4 错误、异常及其处理,6.4.1 编程中的错误 错误是编程中不可避免和必须要处理的问题,编程人员和编程工具处理错误能力在很大程度上影响着编程工作的效率和质量。 一般来说错误分为编译错误和运行错误两

30、种。,1.编译错误,编译错误是由于所编写的程序存在的语法问题,未能通过由源代码到目标码(在Java语言中是由源代码到字节码)的编译过程而产生的,它是由语言的编译系统负责检测和报告。,对于Java的编译错误需要知道: 大部分编译错误是由于对语法不熟悉或拼写失误等引起的; 虽然编译系统会给出每个编译错误的位置和相关的错误信息,使得修改比较简单; 但是由于编译系统判定错误比较机械,在参考它所指出的错误地点和信息时应灵活地同时参照上下文其他语句,将程序作为一个整体来检查。,2.运行错误,运行错误是在程序的运行过程中产生的错误。根据性质不同,运行错误还可分为系统运行错误和逻辑运行错误。 系统错误是指程序

31、在执行过程中引发了操作系统的问题。 逻辑运行错误是指程序不能实现编程人员的设计意图和设计功能而产生的错误。,如何排除运行错误?,排除运行错误,包括系统运行错误和逻辑运行错误,一个非常有效和常用的手段是使用开发环境所提供的单步运行机制和设置断点功能来分解程序运行过程,使之在人为的控制下边调试边运行。 在调试过程中,调试者可以随时检查变量中保存的中间量,设置临时环境,一步步地检查程序的执行过程,从而挖出隐藏的错误。,6.4.2 异常与异常类,异常(Exception),又称为例外,是特殊的运行错误对象,对应着Java语言特定的运行错误处理机制。 异常与其他语言要素一样,是面向对象规范的一部分,是异

32、常类的对象。 Java中定义了很多异常类,每个异常类都代表了一种运行错误,类中包含了该运行错误的信息和处理错误的方法等内容。 每当Java程序运行过程中发生一个可识别的运行错误时,即该错误有一个异常类与之相对应时,系统都会产生一个相应的该异常类的对象,即产生一个异常。,1.异常类结构与组成,Java的异常类是处理运行时错误的特殊类,每一种异常类对应一种特定的运行错误。所有的Java异常类都是系统类库中的Exception类的子类。,Exception类,Exception类有自己的方法和属性,它的构造函数为: public Exception(); public Exception(Strin

33、g s); 第二个构造函数可以接受字符串参数传入的信息,该信息是对该例外所对应的错误的描述。 常用方法包括: public String toString();/返回描述当前Exception类信息的字符串 public void printStackTrace();/功能是完成一个打印操作,在当前的标准输出上打印输出当前例外对象的堆栈使用轨迹,也即程序先后调用执行了哪些对象或类的哪些方法,使得运行过程中产生了这个例外对象。,2.系统定义的运行异常,Exception类有若干子类,每一个子类代表了一种特定的运行时错误。 这些子类有些是系统事先定义好并包含在Java类库中的,称为系统定义的运行异

34、常。 由于预先定义了相应的异常,java程序即使产生一些致命的错误,系统也会自动产生一个对应的异常对象来处理和控制这个错误,避免其蔓延或产生更大的问题。,3.用户自定义的异常,对于某个应用所特有的运行错误,则需要编程人员根据程序的特殊逻辑在用户程序里自己创建用户自定义的异常类和异常对象。这种用户自定义异常主要用来处理用户程序中特定的逻辑运行错误。,public class IllegalSalaryException extends Exception private Employee m_ConcernedEmp; /产生当前错误的Employee对象的引用 private double m

35、_IllegalSalary; /产生当前错误的非法的工资数额 IllegalSalaryException() super(“不合法的起薪:低于最低工资限额“); /调用父类Exception的构造函数 IllegalSalaryException(Employee emp,double iSal) /构造函数 this(); m_ConcernedEmp=emp; /初始化两个属性 m_IllegalSalary=iSal; ,public String toString() String s; if (m_ConcernedEmp!=null) s=“为雇员提供非法工资:雇员号-“+m_

36、ConcernedEmp.getEmpNo()+“非法工资数额-“+m_IllegalSalary+“合法的最低工资数额-“+Employee.getMinSalary(); else s=“给出的工资初始值不合理,不能创建Employee对象“; return s; ,创建用户自定义异常时,一般需要完成如下的工作: (1)声明一个新的异常类,使之以Exception类或其他某个已经存在的系统异常类或用户异常类为父类; (2)为新的异常类定义属性和方法,或重载父类的属性和方法,使这些属性和方法能够体现该类所对应的错误的信息。,6.4.3 异常的抛出,Java程序在运行时如果引发了一个可识别的错

37、误,就会产生一个与该错误相对应的异常类的对象,这个过程被称为异常的抛出。,1.系统自动抛出异常,所有的系统定义的运行异常都可以由系统自动抛出。例: public class TestSystemException public static void main(String args) int a=0,b=5; System.out.println(b/a); ,2.语句抛出的异常,用户程序自定义的异常不可能依靠系统自动抛出,而必须借助于throw语句来定义何种情况是产生了此种异常对应的错误,并应该抛出这个异常类的新对象。格式为: 修饰符 返回类型 方法名(参数列表) throws 异常类名列

38、表 throw 异常类名; ,使用throw语句抛出例外时应注意如下两个问题: (1)一般这种抛出异常的语句应该被定义为在满足一定条件时执行,即用户定义的逻辑错误发生时才执行。 (2)含有throw语句的方法,应该在方法头定义中增加如下的部分: throws 异常类名列表,boolean setEmpSalary(double newsal) throws IllegalSalaryException,IllegalSalaryChangeException if (newsal=m_MaxChgSalRate) throw (new IllegalSalaryChangeException(

39、this,newsal-getEmpSalary(); else /正常情况下,修改工资数额 m_EmpSalary=newsal; return true; ,6.4.4 异常的处理,异常的处理主要包括: 捕捉异常 程序流程的跳转 异常处理语句块的定义,1.捕捉异常,当一个异常被抛出时,应该有专门的语句来接收这个被抛出的异常对象,这个过程被称为捕捉异常。 当一个异常类的对象被捕捉或接收后,用户程序就会发生流程的跳转,系统中止当前的流程而跳转至专门的异常处理语句块,或直接跳出当前程序和Java虚拟机回到操作系统。,在Java程序中,异常对象是依靠以catch语句为标志的异常处理语句块为捕捉和处理的。 每个catch语句还应该与一个try语句块相对应。这个try语句块用来启动Java的异常处理机制,可能抛出异常的语句,包括throw语句、调用可能抛出异常的方法调用语句。,格式如下: try 程序语句块; catch (异常类名 异常形式参数名) 异常处理语句组; ,2.多异常的处理,多异常处理是通过在一个try块后面定义若干个catch块来实现的,每个catch块用来接收和处理一种特定的异常对象。,

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 其他


经营许可证编号:宁ICP备18001539号-1