第9讲Java的继承与多态(一)类的继承子类的创建方法覆盖目标•理解继承的概念•掌握通过父类创建子类的方法•理解子类和父类构造方法的执行顺序•掌握实现方法覆盖的方法面向对象特性概述•继承、封装、多态是面向对象程序设计的3个重要特性。•通过继承,以既有类为基础,派生出新类,达到代码重用的目的;•通过封装,对类对象的数据成员进行访问控制,起到数据保护的作用;•通过多态,程序能够动态的匹配同名方法,使程序更加灵活。继承的基本概念•继承是一种由已有的类创建新类的机制。利用继承,可以先创建一个公有属性的一般类,根据一般类再创建一个具有特殊属性的新类。•新类继承一般类的状态和行为,并根据需要增加它为自己的新的状态和行为。•由此继承而得到的类为子类,被继承的类为父类(超类)。JAVA不支持多继承(子类只能有一个父类)。人学生教师教辅人员外语系学生计算机系学生旅游系学生计算机网络专业学生软件技术专业学生计算机多媒体专业学生计算机教育专业学生classPerson//定义Person类{protectedStringname;protectedStringsex;protectedintage;……Person类的方法}classStudentextendsPerson{privateStringdepartment;//系别privateStringspecialty;//专业……Student类的方法}通过Person类派生出Student类。Student类继承自Person类,拥有Person类的所有方法和属性。通过关键字extends实现继承//Ex6_1.javaclassPerson//定义Person类{protectedStringname;//姓名protectedStringsex;//性别protectedintage;//年龄publicvoidregister(Stringn,Strings,inta)//设置数据成员{name=n;sex=s;age=a;}StringgetName()//获取姓名{returnname;}StringgetSex()//获取性别{returnsex;}intgetAge()//获取年龄{returnage;}publicvoidshowMe()//显示人员信息{System.out.println(姓名:+name+,性别:+sex+,年龄:+age);}}Person类的定义classStudentextendsPerson{//定义Student类,是Person类的子类。privateStringdepartment;//系别privateStringspecialty;//专业publicvoidstudentRegister(Stringn,Strings,inta,Stringdep,Stringspe){//设置数据成员register(n,s,a);department=dep;specialty=spe;}StringgetDepartment()//获取学生所在系{returndepartment;}StringgetSpecialty()//获取学生所学专业{returnspecialty;}publicvoidshowStudent()//显示学生类数据成员{System.out.println(姓名:+name+,性别:+sex+,年龄:+age+,系别:+department+,专业:+specialty);}}通过extends关键字,由Person类派生出Student类publicclassEx6_1{publicstaticvoidmain(Stringargs[]){Studentstudent1=newStudent();student1.studentRegister(张三,男,18,计算机,软件开发);student1.showStudent();}}运行结果:姓名:张三,性别:男,年龄:18,系别:计算机,专业:软件开发程序分析:本例中的Person类是父类,它派生出子类Student类。Student类继承了Person类的name属性,sex属性,age属性,GetName()方法,GetSex(),ShowMe()方法等。同时,Student类对Person类进行了功能扩展,又增加了department,specialty属性和GetDepartment()、GetSpecialty()、ShowStudent()等方法。说明•继承能够使子类拥有(继承)父类的非私有属性和方法(即可以继承public、protected和默认访问属性的成员),而不需要在子类定义时重新定义父类中的这些同名属性和方法。当修改父类中的某个属性和方法时,子类中也会同样得到修改。这样,就可以省去重复定义成员的烦琐,实现代码重用,同时提高了代码的可维护性。•一个父类可以有多个子类,这些子类都是父类的特例,父类描述了这些子类的公共属性和方法。一个子类可以继承它的父类(或祖先类)中的属性和方法,这些属性和方法在子类中不必定义,子类中还可以定义自己的属性和方法。创建子类的语法格式[访问权限]class子类名extends父类名{类体定义;}“访问权限”是指public,private,protected等;子类名和父类名通过关键字extends联系在一起,形成继承关系构造方法的继承•通常在定义一个新类的时候,会定义一个相应的构造方法,用来对数据成员进行一些初始化。•构造方法是在创建对象时自动调用,并执行构造方法的内容,构造方法不需从程序直接调用,而是在对象产生时自动执行。•构造方法没有返回值,名称必须与类的名称相同之外。•假如在一个类中定义了构造方法,而由这个类派生出来的子类也定义了构造方法,那生成新的子类对象的时候,构造方法是怎样执行的呢?//Ex6_2.javaclassPerson//定义Person类{protectedStringname;//姓名protectedStringsex;//性别protectedintage;//年龄publicPerson(){System.out.println(Person()constructoriscalled!);}publicvoidregister(Stringn,Strings,inta)//设置数据成员{name=n;sex=s;age=a;}publicvoidshowMe()//显示人员信息{System.out.println(姓名:+name+,性别:+sex+,年龄:+age);}}Person类的构造方法,输出了字符串“Person()constructoriscalled!”classStudentextendsPerson//定义Student类,是Person类的子类{privateStringdepartment;//系别privateStringspecialty;//专业publicStudent()//定义学生类的构造方法{System.out.println(Student()constructoriscalled!);}publicvoidstudentRegister(Stringn,Strings,inta,Stringdep,Stringspe){register(n,s,a);department=dep;specialty=spe;}publicvoidshowStudent()//显示学生类数据成员{System.out.println(姓名:+name+,性别:+sex+,年龄:+age+,系别:+department+,专业:+specialty);}}子类Student类的构造方法,用于输出“Student()constructoriscalled!”publicclassEx6_2{publicstaticvoidmain(Stringargs[]){Studentstudent1=newStudent();student1.studentRegister(张三,男,18,计算机,软件开发);student1.showStudent();}}运行结果:Person()constructoriscalled!Student()constructoriscalled!姓名:张三,性别:男,年龄:18,系别:计算机,专业:软件开发Person类定义了一个无参构造方法,输出“Person()constructoriscalled!”。通过Person类派生出了Student类,Student类中也定义了一个无参构造方法,将输出“Student()constructoriscalled!”。通过输出结果,明显看出,创建Student对象时,在执行Student类的构造方法之前,调用了Person类的构造方法。这样的执行顺序可以保证子类对象从父类对象继承得到的成员能够进行正确的初始化。覆盖在Ex6_1.java中,Person类通过showMe()方法显示人员信息,而子类Student类通过showStudent()方法显示人员信息。这两个方法都是用来显示人员信息,只是显示的项目不同而已。实际上,在定义Student类方法的时候,可以定义showMe()方法将父类的showMe()方法覆盖。•覆盖是指在子类中,利用完全相同的方法名,返回类型和参数,重新实现父类的某一成员方法。•当需要对象响应同样的方法,但与超类中原来的方法有不同行为时,需要超越(抑制)该方法。用新的方法体取代原来的方法,但使用相同的方法名classPerson{//定义Person类protectedStringname;//姓名protectedStringsex;//性别protectedintage;//年龄publicPerson(){}//构造方法publicPerson(Stringn,Strings,inta){name=n;sex=s;age=a;}publicvoidshowMe(){//显示人员信息System.out.println(姓名:+name+,性别:+sex+,年龄:+age);}}父类Person中定义了showMe()方法,用来输入类对象基本信息覆盖示例classStudentextendsPerson{//定义Person的子类:StudentprivateStringdepartment;//系别privateStringspecialty;//专业publicStudent(Stringn,Strings,inta,Stringdep,Stringspe){name=n;sex=s;age=a;department=dep;specialty=spe;}publicvoidshowMe(){//显示学生类数据成员System.out.println(姓名:+name+,性别:+sex+,年龄:+age+,系别:+department+,专业:+specialty);}}由Person类派生出的Student类中重新定义了showMe()方法,覆盖了父类Person类的showMe()方法。覆盖示例(续)publicclassEx6_3{publicstaticvoidmain(Stringargs[]){Personperson1=newPerson(王兰,女,16);person1.showMe();Studentstudent1=newStudent(“张三”,“男”,18,“计算机”,“网络);student1.showMe();}}运行结果:姓名:王兰,性别:女,年龄:16姓名:张三,性别:男,年龄:18,系别:计算机,专业:网络子类中所定义的showMe()方法覆盖了父类的showMe()方法。例6.1中,Person类对象和Student类对象分别调用showMe()和showStudent()方法才能显示各自信息。本例中