《Java面向对象程序-第6章课件.ppt》由会员分享,可在线阅读,更多相关《Java面向对象程序-第6章课件.ppt(60页珍藏版)》请在taowenge.com淘文阁网|工程机械CAD图纸|机械工程制图|CAD装配图下载|SolidWorks_CaTia_CAD_UG_PROE_设计图分享下载上搜索。
1、第6章 Java的继承与多态 Java教材编写组教学目标通过父类创建子类理解子类和父类构造方法的执行顺序掌握实现方法覆盖的方法掌握super、this、final关键字意义及使用方法理解Object类的作用以及类的常用方法了解多态的意义掌握重载的使用方法概述继承、封装、多态是面向对象程序设计的3个重要特性。通过继承,以既有类为基础,派生出新类,达到代码重用的目的;通过封装,对类对象的数据成员进行访问控制,起到数据保护的作用;通过多态,程序能够动态的匹配同名方法,使程序更加灵活。继承的基本概念继承是一种由已有的类创建新类的机制。利用继承,可以先创建一个公有属性的一般类,根据一般类再创建一个具有特
2、殊属性的新类。新类继承一般类的状态和行为,并根据需要增加它为自己的新的状态和行为。由此继承而得到的类为子类,被继承的类为父类(超类)。Java不支持多继承(子类只能有一个父类)。人学生教师教辅人员外语系学生计算机系学生旅游系学生计算机网络专业学生软件技术专业学生计算机多媒体专业学生计算机教育专业学生class Person /定义Person类protected String name;protected String sex;protected int age;Person类的方法 class Student extends Person private String department;
3、/系别private String specialty;/专业Student类的方法 通过Person类派生出Student类。Student类继承自Person类,拥有Person类的所有方法和属性。通过关键字extends实现继承class Person /定义Person类protected String name;/姓名protected String sex;/性别protected int age;/年龄public void register(String n,String s,int a)/设置数据成员 name=n;sex=s;age=a;String getName()/获
4、取姓名return name;String getSex()/获取性别return sex;int getAge()/获取年龄return age;public void showMe()/显示人员信息System.out.println(姓名:+name+,性别:+sex+,年龄:+age);/Ex6_1.java Person类的定义class Student extends Person /定义Student(学生)类,是Person类的子类。private String department;/系别private String specialty;/专业public void stud
5、entRegister(String n,String s,int a,String dep,String spe)/设置数据成员 register(n,s,a);department=dep;specialty=spe;String getDepartment()/获取学生所在系return department;String getSpecialty()/获取学生所学专业return specialty;public void showStudent()/显示学生类数据成员System.out.println(姓名:+name+,性别:+sex+,年龄:+age+,系别:+departme
6、nt+,专业:+specialty);通过extends关键字,由Person类派生出Student类public class Ex6_1public static void main(String args)Student student1=new Student();student1.studentRegister(张三,男,18,计算机,软件开发);student1.showStudent();运行结果:姓名:张三,性别:男,年龄:18,系别:计算机,专业:软件开发程序分析:本例中的Person类是父类,它派生出子类Student类。Student类继承了Person类的name属性,s
7、ex属性,age属性,GetName()方法,GetSex(),ShowMe()方法等。同时,Student类对Person类进行了功能扩展,又增加了department,specialty属性和GetDepartment()、GetSpecialty()、ShowStudent()等方法。说明继承能够使子类拥有(继承)父类的非私有属性和方法(即可以继承public、protected和默认访问属性的成员),而不需要在子类定义时重新定义父类中的这些同名属性和方法。当修改父类中的某个属性和方法时,子类中也会同样得到修改。这样,就可以省去重复定义成员的烦琐,实现代码重用,同时提高了代码的可维护性。
8、一个父类可以有多个子类,这些子类都是父类的特例,父类描述了这些子类的公共属性和方法。一个子类可以继承它的父类(或祖先类)中的属性和方法,这些属性和方法在子类中不必定义,子类中还可以定义自己的属性和方法。创建子类的语法格式 访问权限 class SonClass(子类名)extends ParentClass(父类名)类体定义;“访问权限”是指public,private,protected等;SonClass是子类名;ParentClass是父类名;这两个类名通过关键字extends联系在一起,形成继承关系 构造方法的继承 通常在定义一个新类的时候,会定义一个相应的构造方法,用来对数据成员进行
9、一些初始化。构造方法是在创建对象时自动调用,并执行构造方法的内容,构造方法不需从程序直接调用,而是在对象产生时自动执行。构造方法没有返回值,名称必须与类的名称相同之外。假如在一个类中定义了构造方法,而由这个类派生出来的子类也定义了构造方法,那生成新的子类对象的时候,构造方法是怎样执行的呢?/Ex6_2.java class Person /定义Person类protected String name;/姓名protected String sex;/性别protected int age;/年龄public Person()System.out.println(Person()construc
10、tor is called!);public void register(String n,String s,int a)/设置数据成员name=n;sex=s;age=a;public void showMe()/显示人员信息System.out.println(姓名:+name+,性别:+sex+,年龄:+age);Person类的构造方法,用于输出”Person()constructor is called!”class Student extends Person /定义Student(学生)类,是Person类的子类private String department;/系别priva
11、te String specialty;/专业public Student()/定义学生类的构造方法 System.out.println(Student()constructor is called!);public void studentRegister(String n,String s,int a,String dep,String spe)register(n,s,a);department=dep;specialty=spe;public void showStudent()/显示学生类数据成员System.out.println(姓名:+name+,性别:+sex+,年龄:+a
12、ge+,系别:+department+,专业:+specialty);子类Student类的构造方法,用于输出“Student()constructor is called!”public class Ex6_2 public static void main(String args)Student student1=new Student();student1.studentRegister(张三,男,18,计算机,软件开发);student1.showStudent();运行结果:Person()constructor is called!Student()constructor is c
13、alled!姓名:张三,性别:男,年龄:18,系别:计算机,专业:软件开发Person类定义了一个无参构造方法,构造方法运行时将输出“Person()constructor is called!”。通过Person类派生出了Student类,Student类中也定义了一个无参构造方法,构造方法运行时将输出“Student()constructor is called!”。通过输出结果,明显看出,创建Student对象时,在执行Student类的构造方法之前,调用了Person类的构造方法。这样的执行顺序可以保证子类对象从父类对象继承得到的成员能够进行正确的初始化。覆盖 覆盖是指在子类中,利用完
14、全相同的方法名,返回类型和参数,重新实现父类的某一成员方法。当需要对象响应同样的方法,但与超类中原来的方法有不同行为时,需要超越(抑制)该方法。用新的方法体取代原来的方法,但使用相同的方法名在Ex6_1.java中,Person类通过showMe()方法显示人员信息,而子类Student类通过showStudent()方法显示人员信息。这两个方法都是用来显示人员信息,只是显示的项目不同而已。实际上,在定义Student类方法的时候,可以定义showMe()方法将父类的showMe()方法覆盖。/Ex6_3.javaclass Person /定义Person类protected String
15、name;/姓名protected String sex;/性别protected int age;/年龄public Person()public Person(String n,String s,int a)/构造方法 name=n;sex=s;age=a;public void showMe()/显示人员信息 System.out.println(姓名:+name+,性别:+sex+,年龄:+age);父类Person中定义了showMe()方法,用来输入类对象基本信息class Student extends Person /定义Student(学生)类,是Person类的子类 pri
16、vate String department;/系别private String specialty;/专业public Student(String n,String s,int a,String dep,String spe)name=n;sex=s;age=a;department=dep;specialty=spe;public void showMe()/显示学生类数据成员 System.out.println(姓名:+name+,性别:+sex+,年龄:+age+,系别:+department+,专业:+specialty);由Person类派生出的Student类中重新定义了sh
17、owMe()方法,覆盖了父类Person类的showMe()方法。public class Ex6_3 public static void main(String args)Person person1=new Person(王兰,女,16);person1.showMe();Student student1=new Student(张三,男,18,计算机,软件开发);student1.showMe();运行结果:姓名:王兰,性别:女,年龄:16姓名:张三,性别:男,年龄:18,系别:计算机,专业:软件开发子类中所定义的showMe()方法覆盖了父类的showMe()方法。当创建Person
18、类对象的时候,Person类的showMe()方法将会执行;当创建Student类对象的时候,Student类的showMe()方法将会执行。例6.1程序Ex6_1.java中,Person类对象和Student类对象分别调用showMe()和showStudent()方法才能显示各自信息。本例中,Person类对象和Student类对象,都可以使用showMe()方法显示信息。利用“覆盖”技术,在子类中可定义和父类中的名称、参数个数与数据类型均完全相同的方法,用以取代父类中原有的方法。super 关键字的使用在Java的覆盖机制中,子类中的同名成员变量或方法隐藏了超类的成员变量或方法,如果在
19、子类中,希望使用父类中的那些被子类覆盖的成员或方法,就需要借助于super这个关键字。另外,若在子类中调用父类的构造方法,也需要利用super实现。super使用方法如下:super.成员变量名称 /使用父类的成员变量super.方法名称 /使用父类的方法this关键字的使用super是Java语言的关键字,用来表示直接父类。为了区别,Java提供this关键字访问当前对象。当在一个类中要明确指出使用当前对象本身的变量或方法时,就可以使用this关键字代表当前类。this的另一个用途是调用当前对象的另一个构造方法。假如一个类中定义了几个构造方法,可以使用this关键字引用当前类中定义的其他构造
20、方法。this使用方法如下:this.成员变量名称 /使用自身成员变量this.方法名称 /使用当前类的方法class Person /定义Person类 protected String name;/姓名 protected String sex;/性别 protected int age;/年龄 public void register(String n,String s,int a)/设置数据成员name=n;sex=s;age=a;public void showMe()/显示人员信息 System.out.println(姓名:+name+,性别:+sex+,年龄:+age);/Ex
21、6_4.java 类Person中定义了3个成员和2个方法register()和showMe()。在方法showMe()中,可以使用this.name来替换name,this代表Person类对象本身。class Student extends Person /定义Student(学生)类,是Person类的子类 private String department;/系别 private String specialty;/专业 public void studentRegister(String n,String s,int a,String dep,String spe)super.reg
22、ister(n,s,a);/调用父类方法this.department=dep;/访问自身成员变量this.specialty=spe;/访问自身成员变量 public void showStudent()/显示学生类数据成员System.out.println(姓名:+super.name+,性别:+super.sex+,年龄:+super.age+,系别:+this.department+,专业:+this.specialty);方法studentRegister()中,使用super表示父类对象,super.register()即调用了父类对象方法register();使用this表示当
23、前类对象,this.department即引用了当前类对象成员department。public class Ex6_4public static void main(String args)Student student1=new Student();student1.studentRegister(张三,男,18,计算机,软件开发);student1.showStudent();运行结果:姓名:王兰,性别:女,年龄:16姓名:张三,性别:男,年龄:18,系别:计算机,专业:软件开发程序分析:Student类中使用super.register()的方式访问父类中定义的register()方法
24、,而访问本身的数据成员,则通过this关键字实现。通常,this关键字可以省略。使用super除了可以访问父类的普通方法外,还可以访问父类的构造方法。/Ex6_5.java class Person /定义Person类 protected String name;/姓名protected String sex;/性别protected int age;/年龄public Person()/构造方法 public Person(String n,String s,int a)/构造方法 name=n;sex=s;age=a;public void showMe()/显示人员信息 System.
25、out.println(姓名:+name+,性别:+sex+,年龄:+age);Person类中定义了2个构造方法,这是方法的重载。程序在调用时会根据实参的个数自动匹配相应的构造方法。class Student extends Person /定义Student(学生)类,是Person类的子类 private String department;/系别 private String specialty;/专业 public Student(String n,String s,int a,String dep,String spe)/定义学生类的构造方法super(n,s,a);/调用了父类的
26、构造方法department=dep;specialty=spe;public void showMe()/显示学生类数据成员 System.out.println(姓名:+name+,性别:+sex+,年龄:+age+,系别:+department+,专业:+specialty);在Student类的构造方法中,使用super(n,s,a)调用了父类构造方法。由于super(n,s,a)有3个实参,程序匹配Person类中定义的构造方法Person(String n,String s,int a)public class Ex6_5public static void main(String
27、 args)Person person1=new Person(王兰,女,16);person1.showMe();Student student1=new Student(张三,男,18,计算机,软件开发);student1.showMe();运行结果:姓名:王兰,性别:女,年龄:16姓名:张三,性别:男,年龄:18,系别:计算机,专业:软件开发程序分析:定义Student类的构造方法时,使用了super()方法访问了父类的构造方法,对相应的数据成员进行了初始化操作。final关键字的使用 覆盖(overriding)固然有其便利性,但在设计类时,如果基于某些因素,父类的方法不希望子类的方法
28、来覆盖它,便可在父类的方法之前加上“final”关键字,如此该方法便不会被覆盖。/Ex6_6.javaclass Person /定义Person类protected String name;/姓名protected String sex;/性别protected int age;/年龄public Person()public Person(String n,String s,int a)/构造方法 name=n;sex=s;age=a;public void showMe()/显示人员信息 System.out.println(姓名:+name+,性别:+sex+,年龄:+age);fin
29、al class Student extends Person /类Student声明为最终类private String department;/系别 private String specialty;/专业 public Student(String n,String s,int a,String dep,String spe)/定义构造方法 super(n,s,a);/调用了父类的构造方法Person(String n,String s,int a)department=dep;specialty=spe;public void showMe()/显示学生类数据成员 System.out
30、.println(姓名:+name+,性别:+sex+,年龄:+age+,系别:+department+,专业:+specialty);使用final关键字将Student类声明成最终类,拒绝继承。class StudentOfComputer extends Student /计算机系学生类 private String grade;/年级编译这个类文件,编译器报错:cannot inherit from final Student。因为Student为final类,所以它拒绝StudentOfComputer继承Student。Object类 在Java中,定义了一个类,这个类抽象了所有类
31、共有的一些属性和方法,这个类的名字是Object。Object类是一切类的父类,所有的类均直接或间接继承它,是类之源。所以,Person类的父类是Object类。Object类类Person类类Student类类Object类的方法 方方 法法主要功能主要功能toString()以String类对象的形式返回当前对象的字符串描述 equals()通过参数带入一个对象,并将它与当前对象进行比较,测试的是两个对象是否相等 getClass()返回一个Class类对象,该对象内部包含了一些能够标识当前对象的信息 hashCode()计算一个对象的哈希码,并将其返回 notify()唤醒一个与当前对象
32、关联的线程 notifyAll()唤醒与当前对象关联的所有线程wait()使线程等待一个指定的时间间隔或等待另一个线程调用当前对象的notify()或notifyAll()方法 getClass()方法的使用 getClass()方法返回一个Class类对象,该对象内部包含了一些能够标识当前对象的信息。如果想知道某个对象obj是属于哪个类时,可用obj.getClass()来查询。class A /声明一个名为A的类 private int num;public A(int a)num=a;public class Ex6_7public static void main(String arg
33、s)A a=new A(1);/声明A类的变量a,并将它指向新的对象Class ca=a.getClass();/用变量a调用getClass()方法System.out.println(class of obj=+ca);运行结果:class of obj=Class AEx6_7的程序代码相当简单,只定义了两个类A与Ex6_7。变量a调用了getClass()方法,这个方法继承自Object类。getClass()方法返回值的类型是Class类。从程序的输出中,类对象a属于类A。输出中含字符串Class,代表A是一个类。equals()方法的使用 equals()方法通过参数带入一个对象,
34、并将它与当前对象进行比较,测试的是两个对象是否相等。如果是,则返回true,否则返回false,Ex6_8是一个简单的范例。class A /声明一个名为A的类 private int num;public A(int a)num=a;public class Ex6_8 public static void main(String args)A a=new A(1);A b=new A(5);A c=a;/声明类变量c,并让它指向变量a所指向的对象Boolean br1=a.equals(b);/测试a与b是否指向同一对象Boolean br2=a.equals(c);/测试a与c是否指向同
35、一对象System.out.println(a.equals(b)=+br1);System.out.println(a.equals(c)=+br2);运行结果:a.equals(b)=falsea.equals(c)=truetoString()方法的使用 toString()方法的功能是将对象的内容转换成字符串,并返回其内容。例如,若变量a是指向由类A所创建的对象时,则下面的语句会调用toString()方法,并输出所指向对象的内容:System.out.println(a);/输出a的内容之前会调用toString方法上面的语句是以类类型的变量a当成println()的参数,此时,Ja
36、va会先用变量a来调用toString()方法,再把结果当成println()的参数。也可以用下面的语法来便编写相同功能,且容易理解的语句:System.out.println(a.toString();/将a转换成字符串,再由println()输出/Ex6_9.javaclass A private int num;public A(int a)num=a;public class Ex6_9 public static void main(String args)A a=new A(2);System.out.println(a.toString();运行结果:A6b97fd覆盖Objec
37、t类的toString()方法/Ex6_10.javaclass A private int num;public A(int a)num=a;public String toString()/覆盖toString()方法 String str=toString()called,num=+num;return str;public class Ex6_10 public static void main(String args)A a=new A(2);System.out.println(a.toString();运行结果:toString()called,num=2重载 所谓的“重载”是指
38、相同的方法名称,若参数个数不同,或参数个数相同、类型不同的话,方法便具有不同的功能。重载是多态技术的一种。多态的定义与作用 多态提供了另外一种分离接口和实现(即把“做什么”与“怎么做”分开)的一种尺度。换句话说多态是在类体系中把设想(想要“做什么”)和实现(该“怎么做”)分开的手段,它是从设计的角度考虑的。如果说继承性是系统的布局手段,多态性就是其功能实现的方法。多态性意味着某种概括的动作可以由特定的方式来实现,这种特定的方式取决于执行该动作的对象。如果从面向对象的语义角度来看,可以简单理解为多态就是“相同的表达式,不同的操作”,也可以说成“相同的命令,不同的操作”。多态有两种情况,一种是上一
39、节的覆盖技术,另外就是重载技术。覆盖是在子类中直接定义和父类同样的属性和方法,但重新编写了方法体,即子类与父类方法的形参与返回值都相同,而内部处理不同,这种方法在使用过程中,Java虚拟机会根据调用这个方法的类来确定哪个方法被调用。class Person /定义Person类 protected String name;/姓名protected String sex;/性别protected int age;/年龄public void register(String n,String s)/设置姓名和性别name=n;sex=s;public void register(int a)/设置
40、年龄 age=a;public void register(String n,String s,int a)/设置数据成员 name=n;sex=s;age=a;public void showMe()/显示人员信息 System.out.println(姓名:+name+,性别:+sex+,年龄:+age);定义了3个register()方法,3个方法具有不同的参数列表。public class Ex6_11public static void main(String args)Person p1=new Person();Person p2=new Person();p1.register
41、(张三,男,18);p2.register(李欣,女);p2.register(17);p1.showMe();p2.showMe();运行结果:姓名:张三,性别:男,年龄:18姓名:李欣,性别:女,年龄:17根据实参的不同,自动匹配调用相应的方法使用重载常犯的错误 运用方法重载需要注意的是,可以定义名称相同,但参数不同的方法;但不可以定义名称相同,而且参数也完全一致的方法。例如,下面的程序代码是行不通的。public void setPerson(int age);public int setPerson(int age);其原因是,一旦调用了setPerson()方法,程序无法判断是哪一个
42、方法被调用。事实上,若尝试编译这样的类,编译器也会出现错误信息。构造方法的重载 在Java中,不仅方法可以重载,构造方法也可以重载。同普通方法的重载,可以在一个类中定义几个构造方法,只要构造方法的参数列表不同即可。请看下面例子。class Personprotected String name;protected String sex;protected int age;public Person()/没有参数的构造方法System.out.println(Person()constructor is called!);public Person(String PName,String PSe
43、x)/有两个变量的构造方法name=PName;sex=PSex;System.out.println(Person(String,String)constructor is called!);System.out.println(姓名:+name+性别:+sex);public Person(String PName,String PSex,int PAge)/有三个变量的构造方法name=PName;sex=PSex;age=PAge;System.out.println(Person(String,String,int)constructor is called!);System.out
44、.println(姓名:+name+性别:+sex+年龄:+age);定义了3个参数不同的构造方法public class Ex6_12 public static void main(String args)Person person=new Person();/调用构造方法Person()Person man=new Person(李明,男);/创建man对象,调用构造方法Person(String,String)Person women=new Person(赵梅,女,19);/创建women对象,调用构造方法Person(String,String,int)运行结果:Person()c
45、onstructor is called!Person(String,String)constructor is called!姓名:李明 性别:男Person(String,String,int)constructor is called!姓名:李明 性别:男Person(String,String,int)constructor is called!姓名:赵梅 性别:女 年龄:19程序分析:类Person中,有三个构造方法,它们的参数表均不相同。这样,就可以用三种不同形式的参数创建并初始化对象。第一个构造方法Person(),它没有任何参数,其作用是输出“Person()construct
46、or is called!”。第二个构造方法Person(String,String),它可分别接收两个类型为String的参数,再将成员设置为对应的值并显示出来。第三个构造方法Person(String,String,int),它可分别接收两个类型为String的参数和一个类型为int的参数,再将成员设置为对应的值并显示出来。重载构造方法,可以在调用时通过参数确定调用哪个方法。在测试类中创建了person,man,women三个对象,通过参数不同分别调用构造方法Person(),Person(String,String),和Person(String,String,int)。实例 一 重载的
47、使用编写一个类,它的功能是计算两个数的和。要求:编写多个求和方法,实现方法的重载。程序将根据参数的类型自动匹配计算和。/Ex6_13.java class Example_Overloading_Addint add(int a,int b)/重载的方法1return(a+b);double add(double x,double y)/重载的方法2return(x+y);double add(double x,double y,double z)/重载的方法3return(x+y+z);定义了3个add()方法,实现了方法的重载public class Ex6_13 public stati
48、c void main(String args)Example_Overloading_Add add=new Example_Overloading_Add();System.out.println(调用两个整型加法的重载方法);System.out.println(结果是:+add.add(3,100);System.out.println(调用三个双精度型加法的重载方法);System.out.println(结果是:+add.add(1.0,23.987,39.369);System.out.println(调用两个双精度型加法的重载方法);System.out.println(结果是
49、:+add.add(59.12,79.123);运行结果:调用两个整型加法的重载方法结果是:103调用三个双精度型加法的重载方法结果是:64.356调用两个双精度型加法的重载方法结果是:138.243 实例二 多态的设计 一个小孩得知邻居家养了几个宠物,但不知是猫是狗还是鸭子。于是丢一块石头到邻居家院中探明真相。这里,宠物作为基类,有一个sound()方法,即发声方法。而猫类,狗类,鸭类等都是宠物类的派生类,各有一个基类sound()的同名覆盖。Animal是一个相对抽象的类。在现实世界中,每个动物都一定属于某个特定的种类,因此,这个类中的sound()成员方法的方法体为空,即本身没有任何特定
50、的操作,只是为了实现多态性而设置。在Dog、Cat和Duck中,覆盖了Animal类中的这个方法,它们根据具体动物的特点发出不同的叫声。小孩丢石头,相当于发出命令调用了宠物类对象的sound()方法。因为小孩并不知道是狗是猫还是鸭子,只知道是宠物。然而实际接收此消息的却是宠物的派生类对象,如果是狗,则输出“Woof Woof”字符串;如果是猫,则输出“Miiaooww”字符串;如果是鸭子,则输出“Quack quackquack”字符串。import java.util.Random;class Animal /动物类protected String type;/种类protected Str