JAVA05进一步讨论对象和类.ppt_第1页
JAVA05进一步讨论对象和类.ppt_第2页
JAVA05进一步讨论对象和类.ppt_第3页
JAVA05进一步讨论对象和类.ppt_第4页
JAVA05进一步讨论对象和类.ppt_第5页
已阅读5页,还剩58页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

5 进一步讨论对象和类 5.1 抽象数据类型 抽象数据类型(数据结构的概念)抽象数据类型(数据结构的概念) (ADT: Abstract Data Types)(ADT: Abstract Data Types) uu由用户定义,用以表示应用问题由用户定义,用以表示应用问题 的数据模型的数据模型 uu由基本的数据类型组成由基本的数据类型组成, , 并包括并包括 一组相关的操作一组相关的操作 uu信息隐蔽和数据封装,使用与实信息隐蔽和数据封装,使用与实 现相分离现相分离 类就是一种抽象数据类型 用一个类来代表某类事物(如动物) 特点: 封装:将实现细节隐藏,使用类时只需知其 功能,不需知道功能如何实现 继承:描述类间的(抽象程度)的层次结构 ,实现代码重用(动物:哺乳动物、爬行动 物) 多态:同一个方法在不同类中运行的结果不 同(“鸣叫”在不同动物类中的表现) 封装的概念 封装的含义:类的设计者把类设计成一个黑匣 子,使用者只能看见类中定义的公共变量和公 共方法,而看不见方法的具体实现细节,也不 能对类中非公共的数据进行操作。 为保护类中成员的正确性或一致性 1、在类的定义中设置对对象中的成员变量和方法进 行访问的权限(使用private、public等关键字); 2、提供一个统一供其他类引用的方法; 3、其他对象不能直接修改本对象所拥有的属性和方 法(而必须通过对象自己提供的方法)。 最常见的封装 将类成员设置成私有(private),外部无法 访问,只有类中的方法可访问 设置一些公开的(public)、专门访问类 成员和为类成员赋值的方法;在这些方法 中可加入一些控制过程,保证对类成员的 访问和改写是合法的。 访问类成员的方法称为getter; 改写类成员的方法称为setter; 简单的封装例子: Students类 (P87页4.10题) public class Student implements Comparable private String name;/ 姓名 private int id;/ 学号 private String sex;/ 性别 private double creditSum;/ 学分积 private Course courses = new Course3;/ 三门课 public String getName() return name; public void setName(String name) = name; public int getid() return id; public void setid(int id) this.id = id; public String getSex() return sex; public void setSex(String sex) this.sex = sex; public Course getG() return courses; public void setG(Course g) this.courses = g; public double getCreditSum() return creditSum; /给学分积赋值,也就是计算学分积 public void setCreditSum() if (courses = null) creditSum = 0; else double sum = 0; for (Course c : courses)/ 对每门课程计算学分积并加到sum中去 if (c.getScore() 94) sum += c.getCredit() * 4.0; else if (c.getScore() 89) sum += c.getCredit() * 3.8; else if (c.getScore() 84) sum += c.getCredit() * 3.6; else if (c.getScore() 79) sum += c.getCredit() * 3.2; else if (c.getScore() 74) sum += c.getCredit() * 2.7; else if (c.getScore() 69) sum += c.getCredit() * 2.2; else if (c.getScore() 64) sum += c.getCredit() * 1.7; else if (c.getScore() 59) sum += c.getCredit() * 1.0; else sum += 0; creditSum = sum; 5.2 对象的构造和初始化 5.2 对象的构造和初始化 要使用对象,首先必须构造它们,并指定 它们的初始状态,然后将方法应用于对象 。 在Java程序设计语言中,使用构造方法 (constructor)来构造新的实例。一个构 造方法是一个新的方法,它的作用是构造 并初始化对象。 5.2 对象的构造和初始化 构造方法是类的一种特殊方法,它的特殊性主 要体现在如下的几个方面: (1)构造方法的方法名与类名相同。 (2)构造方法没有返回类型。 (3)构造方法的主要作用是完成对类对象的初 始化工作。 (4)构造方法不能由编程人员显式地直接调用 。 (5)在创建一个类的新对象的同时,系统会自 动调用该类的构造方法为新对象初始化。 构造方法的特点 (1)构造方法和类具有相同的名字。 (2)一个类可以有多个构造方法。 (3)构造方法可以有0个、1个或多个参数 。 (4)构造方法没有返回值。 (5)构造方法总是和new运算符一起被调 用。 (6)构造方法必须声明为public。 Java中可以不定义构造方法 Java中可以不定义构造方法,此时系统会自动生成一个 默认的构造方法。这个构造方法的名字与类名相同,它 没有任何形式参数,也不完成任何操作。 在类的定义中可以不定义构造方法,而其他类仍然可以 通过调用new classname()来实例化某类对象。这是因 为系统给未定义构造方法的类自动加入了一个特殊的构 造方,这个方法不带参数且方法体为空,称为默认的构 造方法。 用默认的构造方法初始化类对象时,系统把类对象的 数据成员初始化为默认值。 注意:一旦在类中自己定义了构造方法,默认的构造方 法就不被加到类的定义中。此时,如果在程序中初始化 对象时使用了默认的构造方法将出现了编译错误,所以 为了避免此类错误,如果类中定义了构造方法,通常也 加入不带参数的构造方法。 构造方法可以有多个 满足不同的创建对象的方式 不同构造方法之间完全同名,但输入参数 的个数或类型不能相同。 这实际上是方法的重载(overload),见 后 类中只要自定义了一个构造方法,系统为 类准备的默认构造方法就失效了。 如果希望默认的无参数构造方法依然可用, 则需添加一个这样的构造方法 构造方法示例 public class Student private String name;/ 姓名 private int id;/ 学号 private String sex;/ 性别 public Student() /无参数构造方法,可以没有 public Student(String name, int id, String sex)/构造方法 = name; this.id = id; this.sex = sex; /写toString 方法来显示对象的各个属性 /在main方法中创建一个对象并显示其内容 5.3 this引用 5.3 this引用 this是java中的一个关键词,用于在类中指 代所创建的对象本身 通过这种方法使得类中一个方法可调用同 类中的其它方法和成员变量. 例: 构造方法调用另一构造方法 希望在无参数的构造方法中给对象的成员变量赋予默认值 public Student() name=“unknown“; id=0; sex=“unknown“; /this(“unknown“,0,“unknown“); /主程序验证 public static void main(String args) 5.4 子类(和继承) 继承性是软件复用的一种形式。新类由已存在 的类生成,通过保留它们的属性和行为,并且根据 新类的要求对性能加以修改,添加新的属性和行为 。 从现有类出发定义一个新类,称为新类继承了 现有的类,其中被继承的现有类叫做超类( superclass)或父类,由继承而得到的类称为子类( subclass)。 继承 w Super超类 继承super部分 sub1增加部分 继承super部分 sub2增加部分 Sub1子类 Sub2子类 如果子类只从一个父类继承,则称为单继承; 如果子类从一个以上父类继承,则称为多继承。注 意 Java不支持多重继承,但它支持“接口”概念(间 接实现多重继承)。 单重继承 一、父类和子类继承和继承的实现 1、类继承的实现 修饰符 class 类名 extends 父类名 类体; 二、成员变量的继承成员变量的继承 子类继承父类中所有可被子类访问的成员 变量。继承原则如下: w 能够继承那些声明为public和protected的成 员变量。 w 能够继承同一包中的那些默认修饰符的成 员变量。 w 不能继承那些声明为private的成员变量。 w 如果子类声明一个与父类成员变量同名的 成员变量,则不能继承父类的成员变量。 此时子类的成员变量称做隐藏隐藏了父类的成 员变量。 三、成员方法的继承成员方法的继承 子类继承成员方法的规则类似于继承成员变量 的规则:子类继承父类中所有可被子类访问 的成员方法。继承规则如下: w 能够继承那些声明为public和protected的成员 方法。 w 能够继承同一包中的默认修饰符的成员方法 。 w 不能继承那些声明为private的成员方法。 w 不能继承父类的构造方法。 w 如果子类方法与父类方法同名,则不能继承 。子类方法称为覆盖覆盖了父类中的那个方法。 super和this关键字:指代本对象和父对 象 1、super(参数) :基类中的某一个构造方法(必 须作为为构造方法中的第一条语句被使用) 2、this(参数) :本类中另一种形式的构造方法( 必须作为为构造方法中的第一条语句被使用); 3、super: 引用当前对象的直接父类(即上一级或 “父”但并不代表“爷爷”)的对象(用来访问直接 父类中被隐藏的父类中成员数据或方法,基类与 派生类中有相同成员定义时) 4、this:代表当前对象名。其主要的用途:在程 序中易产生二义性之处,应使用this来指明当前 对象;如果方法的形参与类中的成员数据同名, 这时需用this来指明成员变量名 student的子类:postgraduate public class Postgraduate extends Student private String tutor ; /可增加与父类类似的带参数的构造方法 public Postgraduate(String name, int id, String sex,String tutor) super(name,id,sex); this.tutor=tutor; public String getTutor() return tutor; public void setTutor(String tutor) this.tutor = tutor; public String toString() return super.toString()+“. 导师:“+ tutor; /通过主程序验证子类 public static void main(String args) Postgraduate p1=new Postgraduate(“tom“,3014,“male“,“Mary“); System.out.println(p1); 5.5方法的重写 (多态、重写和重载) 重写(又称覆盖) 重写是指在继承过程中,子类中的成员(包括数 据和方法)与其父类中的成员同名,但功能不同 ,此时,子类的成员“覆盖”从父类继承过来的 成员。 w 数据重写:又称为数据隐藏数据隐藏,子类中声明一个 与父类中的成员完全同名的成员(但可以类型 不同),它们实际上是完全不同的两个数据。 此时父类的该成员在子类中不可见; w 方法重写:子类中声明一个与父类的某方法名 称相同,参数表也完全相同(但功能不同)的 方法。此时父类的该方法在子类中不可见。 重写后,父类的对应方法依然可访问 在数据隐藏和方法覆盖后,子类成员覆盖了父类 的同名成员,要访问父类的这些成员,可用 super关键字来引用当前类的父类。super的用 法有3种情况。 1super.变量名:访问父类中被隐藏的成员变 量。 2super.方法名(参数表):调用父类中被重 写的方法。 3super(参数表):调用父类的构造方法,此 时可用super来表示父类的构造方法。 由重写引出“多态” 同名方法在不同的类中(或不同参数时)表现 出不同的功能,称为“多态” 多态机制是面向对象程序设计的一个重要特征 。Java 的多态机制主要表现在方法的重载、构 造方法的重载以及方法的覆盖几个方面。 多态的特点是采用同名的方式,根据调用方法 时传送的参数的多少以及传送参数类型的不同 ,调用不同的方法,这样对于类的编制而言, 可以采用同样的方法获得不同的行为特征。 Java中多态机制有两种 重写(覆盖) 、重载 重写:子类中用完全相同的方法覆盖父类的 方法 重载:同一类中出现名称完全相同,但参数 个数或参数类型不同的多个方法 多态之重载 在编程时我们可能需要在一个类中定义几个功能相似但参 数不同的方法。例如要从3个数中找出其中的最大者, 而每次求最大数时数据类型不同,可能是3个整数、3个 双精度或3个长整数。这样就需要定义三个方法,如: int getMax1(int a,int b,int c) double getMax2(double a,double b,double c) long getMax3(long a,long b,long c) 这种定义方式不仅显得枯燥,而且要求使用这个类的程 序员熟悉多个不同的方法名称,给程序员带来麻烦。有 人会想:能否不用3个方法名称而用一个统一的名称呢 ? 多态之重载 为此,Java语言提供了方法重载(overloading)机制。 方法的重载是允许在一个类的定义中,多个方法使用相 同的方法名。对于上述三个求最大数的方法,利用重载 机制可以进行如下定义: public int getMax(int a,int b,int c) public double getMax(double a,double b,double c) public long getMax(long a,long b,long c) 这样使用一个方法名称getMax就可以定义求各种类型 数据的最大值的方法,程序员只需记住一个方法名,减 轻了程序员的负担,上述例子中getMax方法被重载。 重载的正式定义 就是在类中创建了多个方法,它们具有相同的 名称,但有不同的输入参数和不同的定义。 在调用方法时依据其参数个数及类型自动选择 相匹配的方法去执行。达到各种对象处理类似 问题时具有统一的接口之目的。 多个重载方法的返回值类型可以相同也可以不 相同。无法以返回值类型作为重载方法的区分 标准 对重载的说明:P94 5.1.4 构造方法的重载 在一个类中可以定义多个构造方法,以便对 类对象提供不同的初始化的方法,供用户 选用。 这些构造方法具有相同的名字,而参数的个 数或参数的类型不相同。 这称为构造方法的重载。 重载示例 public class OverloadExp public static void main(String args) OverloadExp demo = new OverloadExp(); System.out.println(demo.getMax(2, 3); System.out.println(demo.getMax(2.3f, 3.5f); System.out.println(demo.getMax(24,4.8f); / 这里到底调用了哪个方法? / 返回较大整数 public int getMax(int i, int j) if (i b) return a; else return b; / 仅仅返回类型不一样不能构成重载 /public double getMax(float a, float b) / /if (a b) / /return a; / else / /return b; / / / 如果只是访问修饰符不一样不能构成重载 /private double getMax(float a, float b) / /if (a b) / /return (double) a; / else / /return (double) b; / / 总结:重写和重载 重写override,又称覆盖: 方法的格式完全相同(名称、自变量的个数 和类型、返回值类型等) 被重写的方法处于不同的类中 重载overload: 只有方法名完全相同,在其它方面(自变量 的个数或类型)必须有至少一项不同 两个重载的方法处于同一类中 5.6 java包 包是一组类的集合 一个包可以包含若干个类文件,还可包 含若干个包 包的作用 将相关的源代码文件组织在一起 类名的空间管理,利用包来划分名字空 间,便可以避免类名冲突 提供包一级的封装及存取权限 类的组织包的概念 包的命名 每个包的名称必须是“独一无二”的 Java中包名使用小写字母表示 命名方式建议 若包名中有任何不可用于标识符的字符,用 下划线替代 若包名中的任何部分与关键字冲突,后缀下 划线 若包名中的任何部分以数字或其他不能用作 标识符起始的字符开头,前缀下划线 类的组织包的概念 一个Java源代码文件称为一个编译单元, 由三部分组成 所属包的声明(省略,则属于默认包) Import (引入)包的声明,用于导入外部的类 类和接口的声明(主体部分) 一个编译单元中只能有一个public类,该 类名与文件名相同,编译单元中的其他类 往往是public类的辅助类,经过编译,每 个类都会产一个class文件 利用包来划分名字空间,便可以避免类名 冲突 编译单元与类空间 包的声明 命名包(Named Packages) 例如: package Mypackage; 当一个类的第一句是这一句时,该类必须位于名 称为“Mypackage”的文件夹中,否则出错; 默认包(未命名的包) 不含有包声明的编译单元是默认包(当前文件夹 )的一部分 类的组织包的概念(续) 包与目录 Java使用文件系统来存储包和类 包名就是文件夹名,即目录名 用javac编译源程序时,如遇到当前目 录(包)中没有声明的类,就会以环境变 量classpath为相对查找路径,按照包 名的结构来查找。因此,要指定搜寻包 的路径,需设置环境变量classpath 类的组织包的概念(续) 引入包 为了使用其它包中所提供的类,需要使用import语句 引入所需要的类 Java编译器为所有程序自动引入包java.lang import语句的格式 import package1.package2. (classname |*); 其中package1.package2表明包的层次,它对应于文件 目录 classname则指明所要引入的类名 如果要引入一个包中的所有类,则可以使用星号(*)来代 替类名 类的组织包的概念(续) 类型private无修饰protectedpublic 同一类yesyesyesyes 同一包中的 子类 noyesyesyes 同一包中的 非子类 noyesyesyes 不同包中的 子类 nonoyesyes 不同包中的 非子类 nononoyes 复习:类成员的访问控制词 Eclipse:自动管理包 包管理虽然很繁琐,但是很规律; Eclipse中可以很方便的管理包 新建包(自动生成对应文件夹) 包中新建类(自动补充“package”语句) 引入其它包中的类(自动寻找类,并补充 “import”语句) 示例 5.7 类成员 一般称为“静态成员”更易识别 类的静态成员 类的静态成员指的是类在实例化之前就存 在的方法和变量(称静态方法和静态变量 ) 因为在产生对象之前就存在,故称为“静态成 员” 如果用来指代与“对象成员”(即对象创建之后 才出现的成员)相异的概念,也可称为“类成 员” 但这样称呼易与“类的成员”相混淆 以修饰词“static”标示静态成员 可以直接通过调来类名来使用。 5.8 关键字 final final 类前面使用“final”,则该类不允许有子类 (也就是不能被继承) 方法前面使用“final”,则该方法不允许被 重写(覆盖) 变量前面使用“final”,则该变量是常量, 不允许被重新赋值。 5.9 抽象类 专门提供给其他类继承的类 抽象类 以“abstract”关键字修饰的类 抽象类是不能直接被实例化的类,因此一般作为 其它类的父类,与final类正好相反; 抽象类中的抽象方法:以“abstract”关键字修饰 的方法 在该类中声明但不在该类中提供实现(也就是方法体 是空的),由继承类提供细节 定义抽象方法的类必须是抽象类. 子类如果继承自抽象类,则必须实现(也就是重写) 抽象类的所有抽象方法;否则它还是一个抽象类,不 能实例化对象 抽象类的例子 import java.util.Scanner; / =抽象类,代码如下: abstract class AbstractGuessNumber private int number, guess = 0; public void setNumber() System.out.print(“想一个数让他猜去,“); this.number = getUserInput();/获得用户输入的整数,令其等于number变量 protected abstract void showMessage(String message); protected abstract int getUserInput(); / 子类中需要重写的两个类 public void begin() showMessage(“欢迎玩猜数字游戏!n “); while (number != guess) guess = getUserInput(); / 获取用户所猜的数字 if (number guess) showMessage(“猜小了,别泄气啊n“); showMessage(“你可算猜对了n“); /=继承抽象类,实现所有抽象方法 class ExtendsGuessNumber extends AbstractGuessNumber private Scanner scanner;/为实现抽象方法getUserinput准备的成员 /*Scanner对象可调用下列方法,读取用户在命令行输入的各种数据类型: nextByte(),nextDouble(),nextFloat,nextInt(),nextLine(),nextLong(),nextShot () 上述方法执行时都会造成堵塞,等待用户在命令行输入数据回车确认.*/ public ExtendsGuessNumber()/构造函数 scanner = new Scanner(System.in); /*Scanner对象可调用下列方法(函数),读取用户在命令行输入的各种数据类型: next.Byte(),nextDouble(),nextFloat,nextInt(),nextLine(),nextLong(),nextShot () 上述方法执行时都会等待用户在命令行输入数据,待回车确认后完成输入.*/ /这是需要实现的抽象方法之一 public void showMessage(String message) for (int i = 0; i 数据成员名=常量值; /声明抽象方法 publicabstract方法名(参数表); 特点: 1、接口的访问控制修饰符只有public。 2、接口类型也可以继承,并且可以多重继承 3、接口体内只能声明常量字段和抽象方法,并且被隐式声明为 public,static,final.当然可写可不写 接口的实现 class 类名 implements 接口名 类体 可实现多个接口,接口名之间以逗号隔开即 可 需在类中实现接口的所有方法 程序5-12 接口定义: public interface Shape2D double pi=3.14; public abstract double area(); 接口必须单独定义在一个文件中 程序5-12 实现接口的类: class Rectangle implements Shape2D int width,height; public Rectangle(int w,int h) width=w; height=h; public double area() return width*height; public class Circle implements Shape2D double radius; public Circle(double r) radius=r; public double area() return (pi*radius+radius); /为了简单,主程序直接放在Circle里面了 public static void main(String args) Rectangle rect=new Rectangle(5,6); System.out.println(“n矩形的面积为:“+rect.area(); Circle cir=new Circle(4); System.out.println(“n圆形的面积为:“+cir.area(); /还可以声明接口类型的变量,令其等于实现了该接口的某个类实例, /然后调用接口的方法(由于变量是接口类型,因此该变量不能调用接口之外的方法) Shape2D s1,s2; s1=rect; s2=cir; System.out.println(“n接口变量s1挂接的对象的面积是:“+s1.area(); System.out.println(“n接口变量s2挂接的对象的面积是:“+s2.area(); 进阶练习:P87 题4.11 提示:创建一个 student类;创建一 个course类(课程) ,包含三门课程的成 绩和学分以及学分积 student中将一个 course实例数组作为 student的成员,这 样每个学生就有了成 绩。 95100分4.0 9094分 3.8 8589分 3.6 8084分 3.2 7579分 2.7 7074分2.2 6569分 1.7 6064分 1.0 60分以下 0 进阶练习:P87 题4.11 在student类的main方法中编写主程序代码,创 建一个学生数组,然后将数组的元素按学分积 排序后从高到低输出 (超出要求的)关键问题:如何根据学分积将 学生排序? 对student类需实现comparable接口使之可以通过 Arrays.sort方法比较大小 该接口只包含一个方法:compareTo,因此必须在 student类中实现该方法; 在compareTo方法中以学分积作为比较依据 import java.util.Arrays; public class Student implements Comparable private String name;/ 姓名 private int id;/ 学号 private String sex;/ 性别 private double creditSum;/ 学分积 private Course courses = new Course3;/ 三门课 / public Student() / / / public Student(String name, int id, String sex)/构造函数 = name; this.id = id; this.sex = sex; public String getName() return name; public void setName(String name) = name; public int getid() return id; public void setid(int id) this.id = id; public String getSex() return sex; public void setSex(String sex) this.sex = sex; public Course getG() return courses; public void setG(Course g) this.courses = g; public double getCreditSum() return creditSum; /给学分积赋值,也就是计算学分积 public void setCreditSum() if (courses = null) creditSum = 0; else double sum = 0; for (Course c : courses)/ 对每门课程计算学分积并加到sum中去 if (c.getScore() 94) sum += c.getCredit() * 4.0; else if (c.getScore() 89) sum += c.getCredit() * 3.8; else if (c.getScore() 84) sum += c.getCredit() * 3.6; else if (c.getScore() 79) sum += c.getCredit() * 3.2; else if (c.getScore() 74) sum += c.getCredit() * 2.7; else if (c.getScore() 69) sum += c.getCredit() * 2.2; else if (c.getScore() 64) sum += c.getCredit() * 1.7; else if (c.getScore() 59) sum += c.getCredit() * 1.0; else sum += 0; creditSum = sum; /为了实现student可比较大小必须有的函数,属于Comparable接口 public int compareTo(Object o) double d = (Student) o).getCreditSum();

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论