为了正常的体验网站,请在浏览器设置里面开启Javascript功能!

第5章 Java面对对象的程序设计(二)

2012-04-10 46页 ppt 409KB 29阅读

用户头像

is_431020

暂无简介

举报
第5章 Java面对对象的程序设计(二)null第4章 Java面对对象的程序设计(二)第4章 Java面对对象的程序设计(二)学习导读学习导读本章讨论面向对象的编程(OOP)及其关键技术:继承和多态、接口、包。 继承性是软件复用的一种形式,对降低软件复杂性行之有效。继承性同时是面向对象程序设计语言的特点,采用对象但没有继承性的语言是基于对象的语言,但不是面向对象的语言,这是两者的区别。 多态性允许以统一的风格处理已存在的变量及相关的类,使增加系统中新功能变得容易。5.1 继承的概念5.1 继承的概念 继承性是面向对象程序设计语言的最主要的特点,是其他语言(如面...
第5章  Java面对对象的程序设计(二)
null第4章 Java面对对象的程序(二)第4章 Java面对对象的程序设计(二)学习导读学习导读本章讨论面向对象的编程(OOP)及其关键技术:继承和多态、接口、包。 继承性是软件复用的一种形式,对降低软件复杂性行之有效。继承性同时是面向对象程序设计语言的特点,采用对象但没有继承性的语言是基于对象的语言,但不是面向对象的语言,这是两者的区别。 多态性允许以统一的风格处理已存在的变量及相关的类,使增加系统中新功能变得容易。5.1 继承的概念5.1 继承的概念 继承性是面向对象程序设计语言的最主要的特点,是其他语言(如面向过程语言)所没有的。 类之间的继承关系是现实世界中遗传关系的直接模拟,它示类之间的内在联系以及对属性和操作的共享,即子类可以沿用父类(被继承类)的某些特征。当然,子类也可以具有自己独立的属性和操作。继承5.1 继承的概念5.1 继承的概念继承定义 继承性是软件复用的一种形式。新类由已存在的类生成,通过保留它们的属性和行为,并且根据新类的要求对性能加以修改,添加新的属性和行为。 如果子类只从一个父类继承,则称为单继承;如果子类从一个以上父类继承,则称为多继承。注意 Java不支持多重继承,但它支持“接口”概念。接口使Java获得了多重继承的许多优点,摒弃了相应的缺点。 5.2 扩展类5.2 扩展类1 继承关系定义 父类名跟在extends 关键字后面,用来说明当前类是哪个已经存在类的子类,存在继承关系。 定义 雇员类 Employee 的两个子类: 一般雇员类:CommonEmployee 主 管 类:ManagerEmployee子类从父类继承有两个主要的方面: (1)属性的继承。例如,公司是一个父类,一个公司有名称、地址、经理、雇员等,这些都属于结构方面。 (2)的继承。一个父类定义了若干操作,如一个公司要有项目、利润、任命经理、录用职工等操作,子公司也将继承这些行为。 5.2 扩展类5.2 扩展类 class CommonEmployee extends Employee //子类1: { int m_ManagerNo ;//定义类属性m _ManagerNo,代表雇员上司的编号 } class ManagerEmployee extends Employee //子类2: { int m_SecretaryNo; //定义类属性m_SecretaryNo,代表秘书的编号 }声明类头-父类名两个子类5.2 扩展类5.2 扩展类2 属性继承与隐藏 尽管Employee类是一个父类,但是并不因为它是父类就意味着它有更多的功能。恰恰相反,子类比它们的父类具有更多的功能。因为子类是父类的扩展,增加了父类没有的属性和方法 (1)子类不能访问父类的private成员,但子类可以访问其父类的public, (2)protected访问是public和private访问之间一个保护性的中间层次。 (3)由于被继承的父类成员没有在子类声明中列出,但是这些成员确实存在于子类中。 5.2 扩展类5.2 扩展类3 方法继承、覆盖与重载 1).方法继承 对于子类对象,可以使用父类中的方法。即使这些方法没有明显地在子类中定义,它们也自动地从父类中继承过来了。 2).方法覆盖 方法的覆盖是指:子类定义同名方法来覆盖父类的方法,是多态技术的一个实现。当父类方法在子类中被覆盖时,通常是子类版本调用父类版本,并做一些附加的工作。 见例5.1 例5.2 5.2 扩展类5.2 扩展类关于覆盖应注意的事项 1、方法覆盖中,子类在重新定义父类已有的方法时,应保持与父类完全相同的方法头声明,即与父类完全相同的方法名、返回值和参数列表。 2、子类可以添加字段,也可以添加方法或者覆盖父类中的方法。然而,继承不能去除父类中的任何字段和方法。 3、注意方法覆盖中的this和super 见下页: 5.2 扩展类5.2 扩展类this和super 1、this表示的是当前对象本身,this代表当前对象的一个引用。可以理解为对象的另一个名字。利用this可以调用当前对象的方法和属性。 如:this.getName()和getName()在类中是一样的。见例1this的使用 2、super表示的是当前对象的直接父类对象,是当前对象的父类对象的引用。见例2 super的使用 5.2 扩展类5.2 扩展类3.方法重载 重载的定义:可以用相同的方法名但不同的参数表来定义方法(参数表中参数的数量、类型或次序有差异),这称为方法重载。 重载(overloading):当多个方法具有相同的名字而含有不同的参数时,便发生重载。编译器必须挑选处调用哪个方法。它通过将在不同方法头部中的参数类型和在特定的方法调用中使用值的类型进行比较,从而挑选出正确的方法。 5.2 扩展类5.2 扩展类4 在子类中使用构造函数 关于子类构造函数的规律如下: (1)子类构造函数总是先调用(显式的或隐式地)其父类的构造函数,以创建和初始化子类的父类成员。 (2)构造函数不能继承,它们只属于定义它们的类。 (3)当创建一个子类对象时,子类构造函数首先调用父类的构造函数并执行,接着才执行子类构造函数 5.2 扩展类5.2 扩展类5 父类对象与子类对象的关系 1、子类对象可以被视为是其父类的一个对象; 2、父类对象不可被当作某个子类的对象; 3、如果一个方法的形式参数定义的是父类对象,那么调用这个方法时可以使用子类对象作为实际参数 4、如果父类对象引用指向的实际是一个子类对象,那么父类对象的引用可以强制类型转换为子类对象的引用 例:Employee e 5.2 扩展类5.2 扩展类5 父类对象与子类对象的关系 调用过程:e. getSalary() 程序会选择正确的getSalary方法。注意尽管e的声明类型是Employee. 当e指向一个Employee对象时,e.getSalary()会调用Employee类中的getSalary方法;而当e指向一个Manager对象时,getSalary()方法就变成了Manager类的getSalary()方法。虚拟机知道e所指对象的实际类型,因此它会调用正确的方法。 事实上,一个对象变量(如e)可以指向多种实际类型这种现象称为“多态”。在运行时自动选择正确的方法进行调用称作动态绑定。 5.2 扩展类5.2 扩展类6 扩展类继承的应用示范 现在讨论一个继承性的具体例子,点、圆的层次结构。首先建立并使用Point类,然后从point类继承产生Circle类。见例3 程序的模块: (1)模块1:程序定义了一个Point类; (2)模块2:又定义了Circle类,它是从Point类继承来的; (3)应用程序,该程序演示了如何把子类引用指定为父类引用,以及把父类引用强制转换为子类引用,注意当p添加到string时对toString的隐式调用 5.2 扩展类5.2 扩展类用来完成这个效果的两项关键编程技术是: (1)创建Circle类继承了Point类。 (2)在Point类和Circle类中用完全相同的覆盖toString方法。 值得强调的是以下几点: (1)Java将隐式地把Object类(java.lang包)作为新定义类的父类。Object类提供了一套任何类的任何对象均可使用的方法。 (2)子类构造函数总是先调用(显式的或隐式地)其父类的构造函数,以创建和初始化子类的父类成员;构造函数不能继承,它们只属于定义它们的类。 (3)父类的实例变量可用Protected限定,因此,从Point衍生Circle类时,Circle类的方法能直接引用坐标x和y,而不必使用访问。5.3 多态与动态绑定5.3 多态与动态绑定多态(Polymorphism)提高了程序可扩充性,调用多态性行为的软件传送给对象的消息(即方法调用)与对象的类型无关,因此能响应已有消息的新类型可以直接加入系统,而不用修改基本系统。 在运行时自动选择正确的方法进行调用称作动态绑定(dynamic binding)。 在编译时可以选择正确的方法进行调用称作静态绑定(static binding) 5.3 多态与动态绑定5.3 多态与动态绑定1 多态 对于数据来说,继承是否为正确的设计可以用一个简单的规则来判断。“is-a”规则表明子类的每一个对象都是一个超类的对象。例如,每一个经理是一个员工。然而,只有经理类是员工类的子类才是有意义的。很明显,反过来就不行了——并不是每个员工都是经理。 还有一个明确叙述“is-a”规则的方法是替代原则。该原则规定无论何时,如果程序需要一个超类对象,都可以用一个子类对象来代替5.3 多态与动态绑定5.3 多态与动态绑定2 动态绑定 理解调用一个对象方法的机制是非常重要的。下面具体介绍:X.f; (1)编译器检查对象的声明类型和方法名。 (2)接着,编译器检查方法调用中的参数类型。如果在所有的叫做f的方法中有一个其参数类型同调用提供的参数类型最匹配,那么该方法就会被选择调用。这个过程称作超载选择。(静态) (3)当程序运行并且使用动态绑定来调用一个方法时,那么虚拟机必须调用同x所指向的对象的实际类型相匹配的方法版本。 动态绑定是非常重要的特性:它能使程序变得可扩展而无需重编译已存代码。5.3 多态与动态绑定5.3 多态与动态绑定例 见书P84例5。4和例5。5 5.4 构造函数的继承与重载5.4 构造函数的继承与重载构造函数的作用是来定义对象的初始状态。然而由于对象的构造如此重要,Java还另外提供了一些不同的机制来编写构造函数 默认属性初始化 如果在构造函数中没有明确地给某个属性赋值,那么此字段会被自动地赋值以一个默认值:若是数字则被赋值以0,若是布尔类型则被赋值以false,若是对象引用则被赋值以null。但使用默认值被认为是一种糟糕的编程做法。因为,如果字段以不可见的形式被初始化会使得别人很难读懂程序。 5.4 构造函数的继承与重载5.4 构造函数的继承与重载默认构造函数 默认构造函数是指没有参数的构造函数(这种构造函数有时也称作无参数构造函数)。例如,下面是—个Employee类的默认构造函数: public Employee() { name=””; salary=0; hireDay=new Date(); } 如果编写了一个没有构造函数的类,则系统会自动为此类提供一个默认构造函数。此默认构造函数将所有的实例字段初始化为默认值。 5.4 构造函数的继承与重载5.4 构造函数的继承与重载3 显式属性初始化 由于在类中可以重载构造函数方法,所以可以采用多种方式来设置类中实例属性的初始状态不管什么样的构造函数调用,确保每个实例字段都被设置为某个有意义的值是一种很好的习惯。 在类的定义中,可以简单地把一个值赋值给任何字段。例如, private String name=”lili” 在执行构造函数前,此赋值会被执行。当类中所有的构造函数都需要把某一特定的实例字段赋值以相同的值时,此语法非常有用5.4 构造函数的继承与重载5.4 构造函数的继承与重载参数名 当编写小的构造函数时,一般选择单个字母作为参数名。 public Employee(String n,double s) { name=n; . salary=s; } 然而,这么做的缺点是需要阅读代码才能知道参数n和s表示的是什么。 5.4 构造函数的继承与重载5.4 构造函数的继承与重载5 构造函数重载 在一个类中可以定义多个构造函数以满足不同的对象实例的初始化情况,这些构造函数通过不同的参数列表来区分。 Public Employee(String n){ } public Employee(String n,double s){ } Public Employee(String n,double s,int ayear,int amonth,int aday){ } 5.4 构造函数的继承与重载5.4 构造函数的继承与重载6 调用另一个构造函数 关键字this指向隐式参数。此外,此关键字还有另一种含义。如果构造函数第一个语句具有形式this(……),那么此构造函数调用此类中的另一个构造函数。下面是一个典型的实例: Public Employee(String,double){ } public Employee(double s) { //calls Employee(String,double) this(“Employee #”+nextId,s); nextId++; } 5.4 构造函数的继承与重载5.4 构造函数的继承与重载调用父类的构造函数 关键字super指向当前类的直接父类对象。此外,此关键字还有另一种含义。如果构造函数第一个语句具有形式this(……),那么此构造函数调用此类的直接父类中的另一个构造函数。: Public Employee(String,double){ }//处于类Employee中 public Manager(double s)//处于类Manager中,为Employee的子类 { //calls Employee(String,double)in calss Employee super(“Employee #”+nextId,s); nextId++; } 5.5 包5.5 包1 包用途 Java允许把多个类收集在一起成为一组,称作包(package)。包便于组织任务,以及使自己的任务和其他人提供的代码库相分离。 标准Java库被分类成许多的包,其中包括java.1ang、java.util和java.net等等。标准Java包是分层次的。就像在硬盘上嵌套有各级子目录一样,可以通过层次嵌套组织包。所有的Java包都在Java和Javax包层次内5.5 包5.5 包2 创建包 已经看到,已有的库,比如Java API中的类和接口,可以导入到Java程序中。 Java API中的每一个类和接口属于一个特定的包。它包含一组相关联的类和接口,实际是对类和接口进行组织的目录结构。 例如,假定文件名是MyClass.java。它意味着在那个文件有一个、而且只能有一个public类。而且那个类的名字必须是MyClass(包括大小写形式): package mypackage; public class MyClass { …… } { …… } 5.5 包5.5 包创建可复用的类的步骤简要说明如下: (1)定义一个public类。如果类不是public,它只能被同一包中的其他类使用。 (2)选择一个包名,并把package语句加到可复用的类的源代码文件中。 (3)编译这个类。这样,它就被放到适当的包目录结构中,以供编译器和解译器使用。 (4)把这个可复用的类导入到需要用它的程序中。现在就可以使用它了。 注意 在Java语言中可以出现在类定义的括号外面的仅有两个语句,它们是package和import。5.5 包5.5 包包引用---每个类名前加上完整的包名 例如,给出一个指向此包中的类的快捷方式。一旦使用import(导入)了以后,就不再需要给出完整的包名。 可以引入一个特定的类,也可以引入整个包。import语句要放在源文件的头部(但在所有package语句的下面)。例如,可以通过下面的语句引入在java.util包中的所有的类: import java.util.*; 然后,就可以使用 Date today=new Date(); 而不需要在前面加上包名。也可以引入包中某个特定的类: import java.util.Date; 5.5 包5.5 包要把类放人一个包中,必须把此包的名字放在源文件头部,并且放在对包中的类进行定义的代码之前。例如,在文件Employee.java的开始部分如下: package com.horstmann.corejava; public class Employee { …… } 把包中的文件放入与此完整的包名相匹配的子目录中。例如,在包com.horstmann.corejava中的所有的类文件都必须放在子目录com/horstmann/core.java(Windows下的com\horstmann\corejava)下。这是最简单的一种方法,在本章的后面可以看到更多的选项。5.5 包5.5 包类被存储在文件系统的子目录中。类的路径必须与所在包名相匹配。 在前面的例子中,包目录com/horstmann/corejava是程序目录的一个子目录。然而这样安排很不灵活。一般,有多个程序需要访问包文件。为了使包可以在多个程序间共享,需要做以下事情: 1)把类放在一个或多个特定的目录中,比如/home/user/classdir。此目录是包树的基本目录。如果加入了类com.horstmann.corejava.Employee,那么此类文件必须位于子目录/home/user/classdir/com/horstmann/corejava下。 2)设置类路径。类路径是其子目录包含类文件的所有基本目录的集合。 classpath 5.5 包5.5 包已经接触过public和private访问指示符。 被标记为Public的部件可以被任何类使用,而私有部件只能被定义它们的类使用。如果没有指定public或private,那么部件(即类、方法或变量)可以被同一个包中的所有方法访问。5.5 包5.5 包4 Java API包 为了简化面向对象的编程过程,Java系统事先设计并实现了一些体现了常用功能的标准类,如用于输入/输出的类,用于数学运算的类,用于图形用户界面设计的类,用于网络处理的类等。这些系统标准类根据实现的功能不同,可以划分成不同的集合,每个集合是一个包,合称为类库。可以引用这些包,也可以创建自己的包。 Java的类库是系统提供的已实现的标准类的集合,是Java编程的API,它可以帮助开发者方便、快捷地开发Java程序 5.6 接口5.6 接口在Java语言中,接口(Interface)是对符合接口需求的类的一套。接口与包相似,也是用来组织应用中的各类并调节它们的相互关系的一种结构,更准确地说,接口是用来实现类间多重继承功能的结构 1 接口概念 接口主要作用是可以帮助实现类似于类的多重继承的功能。在Java中,出于简化程序结构的考虑,不再支持类间的多重继承而只支持单重继承,即一个类至多只能有一个直接父类。然而在解决实际问题的过程中,仅仅依靠单重继承在很多情况下都不能将问题的复杂性表述完整,需要其他的机制作为辅助。 5.6 接口5.6 接口2 接口声明 Java中声明接口的语法如下: [public] interface 接口名 [extends 父接口名列表] { //接口体; //常量域声明 [public] [static] [final] 域类型 域名=常量值; //抽象方法声明 [public] [abstract] 返回值 方法名(参数列表) [throw异常列表]; } 从上面的语法规定可以看出,定义接口与定义类非常相似,实际上完全可以把接口理解成为一种特殊的类,接口是由常量和抽象方法组成的特殊类5.6 接口5.6 接口(1)接口中的属性都是用 final修饰的常量, (2)接口中的方法都是用abstract修饰的抽象方法,在接口中只能给出这些抽象方法的方法名、返回值和参数列表,而不能定义方法体,即仅仅规定了一组信息交换、传输和处理的“接口”5.6 接口5.6 接口2 接口的实现 一个类要实现某个或某几个接口时,有如下的步骤和注意事项: (1)在类的声明部分,用implements关键字声明该类将要实现哪些接口; 如下: class 类名 implements 接口{ } 5.6 接口5.6 接口(2)如果实现某接口的类不是abstract的抽象类,则在类的定义部分必须实现指定接口的所有抽象方法,即为所有抽象方法定义方法体,而且方法头部分应该与接口中的定义完全一致,即有完全相同的返回值和参数列表; (3)如果实现某接口的类是abstract的抽象类,则它可以不实现该接口所有的方法。 (4)一个类在实现某接口的抽象方法时,必须使用完全相同的方法头。 (5)接口的抽象方法,其访问限制符都已指定是public,所以类在实现方法时,必须显式地使用public修饰符。 见书86例5。6 例5。7 例5。8 多态5.6 本章小结5.6 本章小结面向对象编程的优点之一是可通过继承性实现软件复用。新类通过继承性可继承父类已定义过的实例变量和方法。在这种情况下,新类叫做子类。单一继承是指一个子类继承一个父类。 多重继承是指一个子类继承多个父类。Java不支持多重继承,但Java提供了接口。 在子类中通常要加入它自己的实例变量和方法,所以子类一般要比它的父类大。另一方面,子类比父类更具体,因而代表了较少的对象5.6 本章小结5.6 本章小结子类不能访问父类的private成员,但子类可以访问其父类的public,protected和包访问成员;要访问父类的包访问成员,子类一定要在父类的包内。 子类构造函数总是先调用(显式的或隐式地)其父类的构造函数,以创建和初始化子类的父类成员。 继承性实现了软件的复用,这不但节省了开发时间,也鼓励人们使用已经验证无误和调试过的高质量软件。 子类的对象可以当作其父类的对象对待,反之则不行。 5.6 本章小结5.6 本章小结父类和子类的关系是一种层次结构关系。当一个类使用继承性机制时,它可以是为其他类提供属性和行为的父类,也可以是继承那些属性和行为的子类。 继承性层次结构的层次数只受系统硬件结构的限制,但大多数层次结构只有几层。层次结构对于理解和管理复杂软件非常有用。 随着软件复杂性的增加,Java提供了通过继承性和多态性支持层次结构的机制。 protected访问是public和private访问之间一个保护性的中间层次。父类方法、子类方法和在同一个包内类的方法都能访问父类的protected成员,但其他方法均不能访问5.6 本章小结5.6 本章小结父类可以是一个子类的直接父类或间接父类。直接父类是子类显式使用extends说明的类,间接父类是子类从层次结构树的前几层上继承的类。当父类某成员不适合一个子类时,可以在子类中覆盖它。 一个子类对象引用可以隐式地转换成一个父类对象引用。使用显式的类型转换,可以把父类引用转换成子类引用。如果目标不是子类对象,将产生Class CastException例外处理。 父类代表共性,从一个父类派生的所有类都继承了这个父类的功能。 5.6 本章小结5.6 本章小结当通过父类引用调用一个方法时,Java会正确地选择与那个对象对应的类的覆盖方法。在多态性中,一个方法调用可能会产生不同动作,这取决于接受调用的对象类型。 当从具体类(子类)中实例化某些对象时,这些引用可以用来对这些对象进行多态性操作。经常要把一些新类加入系统,这时可以用动态方法绑定(也称迟绑定)接纳它们。在编译方法调用时,不需要知道对象的类型。只有执行时,才会选择相应对象的方法。 在动态方法绑定中,执行方法调用时系统将会找到接受调用对象所属的类的相应方法。对于父类提供的方法,子类可以覆盖它的父类版本。 5.6 本章小结5.6 本章小结一个接口的定义由关键字interface开始以包含pubic final static数据。但这不是必须的,即子类也可以使用一个方并包含一套public abstract方法,接口也可为使用接口,一个类必须声明实现(关键字implements)接口,指定的参数个数和返回类型定义每个方法。当没有缺省的实现用来继承时,通常使用接口而不使用抽象类。 当某个类实现一个接口时,也有同样的“是一个”继承性关系。并且必须根据接口中为实现一个以上的接口,只要在类定义中的关键字implements后面列出接口名逗号分隔。
/
本文档为【第5章 Java面对对象的程序设计(二)】,请使用软件OFFICE或WPS软件打开。作品中的文字与图均可以修改和编辑, 图片更改请在作品中右键图片并更换,文字修改请直接点击文字进行修改,也可以新增和删除文档中的内容。
[版权声明] 本站所有资料为用户分享产生,若发现您的权利被侵害,请联系客服邮件isharekefu@iask.cn,我们尽快处理。 本作品所展示的图片、画像、字体、音乐的版权可能需版权方额外授权,请谨慎使用。 网站提供的党政主题相关内容(国旗、国徽、党徽..)目的在于配合国家政策宣传,仅限个人学习分享使用,禁止用于任何广告和商用目的。

历史搜索

    清空历史搜索