2.3.2 重写
当同名方法同时存在于子类和父类中时,对于子类来说就是将继承的父类的方法重新写过了,实现功能完全可以和父类无关。当调用子类的方法时,运行的是子类重新改写的方法,而不是父类的方法。
【例2-11】 重写方法的调用。
class A { void display() { System.out.println("这是父类的方法"); } void print() { System.out.println("A's method print() called!"); } } class B extends A{ // 子类B派生自父类A void display(){ // 方法的重写 System.out.println("这是子类的方法"); } } public class Test { public static void main(String args[]) { A a1=new A(); //a1引用类A的实例 a1.display(); a1.print(); A a2=new B(); //a2引用类B的实例,子类对象可以看做父类对象 a2.display(); a2.print(); } }
该程序的运行结果为:
这是父类的方法 A's method print() called! 这是子类的方法 A's method print() called!
Java运行时,系统分析是类A的一个实例还是类B的一个实例,以决定是调用类A的方法display()还是调用类B的方法display()。
特别提示:
方法的覆盖中需注意的是,子类在重写父类已有的方法时,应保持与父类完全相同的方法头声明,即应与父类有完全相同的方法名、返回值和参数列表。否则,就不是方法的覆盖,而是在子类定义自己的与父类无关的成员方法。
方法重写时要遵循三个原则:
(1)重写方法的返回类型必须与它所重写的方法相同。
(2)重写方法不能比它所重写的方法有更严格的访问权限,也就是子类private方法不能覆盖掉父类public的方法。
(3)重写方法不能比它所重写的方法抛出更多的异常。
进行方法重写时必须遵循这三个原则,否则编译器会指出程序出错。
工作分解-操作方案
1.分析抽象出类;
2.按照类图编制出类框架;
3.实现类方法;
4.创建对象;
5.调用对象中的方法完成具体功能。
工作实施
1.分析抽象出类
从本任务中,我们可以分析出共有三个类:People(人)类是父类,Student(学生)类和Teacher(教师)类都是People类的子类。People类有两个非私有属性:姓名name和年龄age;四个成员方法:一个无参构造方法(用于将属性初始化为其默认值),一个带参构造方法,一个表示“人”说话行为的方法talk(),以及表示“人”工作行为的方法work()。Student类除了从父类People继承的成员外还新增了一个属性:学号sNo和重写父类People的两个方法:talk()和work();Teacher类除了从父类People继承的成员外还新增了一个属性:教师号tNo和重写父类People的两个方法:talk()和work()。如图2-7所示。
图2-7 人(People)、学生(Student)和教师(Teacher)类图
2.按照类图编制出类框架
// 人类(是学生类和教师类的父类) class People { String name; // 姓名 int age; // 年龄 public People(){ // 无参构造方法 } public People(String name,int age){ // 带参构造方法 } public void talk(){ // 说话行为 } public void work(){ // 工作行为 } } // 学生类,派生自People类 class Student extends People{ String sNo; // 学号 // 构造方法 public Student(String name, int age, String sNo) { } // 以下重写继承自父类的方法 public void talk(){ // 说话行为 } public void work(){ // 工作行为 } } // 教师类,派生自People类 class Teacher extends People { String tNo; // 教师号 public Teacher(String name, int age, String tNo) { } // 以下重写继承自父类的方法 public void talk(){ // 说话行为 } public void work(){ // 工作行为 } }
3.实现类中的方法
// 实现People类中的方法 public People(){ // 无参构造方法 name = ""; age = 0; } public People(String name,int age){ // 带参构造方法 this.name = name; this.age = age; } public void talk(){ // 说话行为 System.out.println("人会说话"); } public void work(){ // 工作行为 System.out.println("人会工作"); } // 实现Student类中的构造方法 public Student(String name, int age, String sNo) { super(name,age); // 调用父类的带参构造方法 this.sNo = sNo; } /***** 以下重写继承自父类的方法**********/ public void talk(){ // 说话行为 System.out.println("学生正在回答老师的提问"); } public void work(){ // 工作行为 System.out.println("学生的主要工作是学习"); } // 实现Teacher类中的构造方法 public Teacher(String name, int age, String tNo) { super(name,age); // 调用父类的带参构造方法 this.tNo = tNo; } /***********以下重写继承自父类的方法*************/ public void talk(){ // 说话行为 System.out.println("老师正在讲课"); } public void work(){ // 工作行为 System.out.println("教师的主要工作是教书育人"); }
4.定义主类
public class Test { public static void main(String[] args) { } }
5.创建类的对象
Student s=new Student("张三",18,"0900104"); // 创建学生类对象 Teacher t=new Teacher("lee",20,"2009001"); // 创建教师类对象
6.访问对象
// 打印学生对象的信息 System.out.println("学生的姓名:" + s.name + "\t年龄:" + s.age + "\t学号:" + s.sNo); s.talk(); s.work(); // 打印教师对象的信息 System.out.println("教师的姓名:" + t.name + "\t年龄:" + t.age + "\t教师号:" + t.tNo); t.talk(); t.work();
7.代码调试并运行
(1)完整源代码如下:
/** * 人类 */ class People { String name; // 姓名 int age; // 年龄 public People(){ // 无参构造方法 name = ""; age = 0; } public People(String name,int age){ // 带参构造方法 this.name = name; this.age = age; } public void talk(){ // 说话行为 System.out.println("人会说话"); } public void work(){ // 工作行为 System.out.println("人会工作"); } } /** * 学生类,派生自People类 */ class Student extends People { String sNo; // 学号 // 构造方法 public Student(String name, int age, String sNo) { super(name,age); // 调用父类的带参构造方法 this.sNo = sNo; } // 以下重写继承自父类的方法 public void talk() { System.out.println("学生正在回答老师的提问"); } public void work(){ // 工作行为 System.out.println("学生的主要工作是学习"); } } /** * 教师类,派生自People类 */ class Teacher extends People { String tNo; // 教师号 public Teacher(String name, int age, String tNo) { super(name,age); // 调用父类的带参构造方法 this.tNo = tNo; } // 以下重写继承自父类的方法 public void talk(){ // 说话行为 System.out.println("老师正在讲课"); } public void work(){ // 工作行为 System.out.println("教师的主要工作是教书育人"); } } public class Test { public static void main(String[] args) { Student s = new Student("张三", 18, "0900104"); System.out.println("学生的姓名:" + s.name + "\t年龄:" + s.age + "\t学号:" + s.sNo); s.talk(); s.work(); Teacher t = new Teacher("lee", 20, "2009001"); System.out.println("教师的姓名:" + t.name + "\t年龄:" + t.age + "\t教师号:" + t.tNo); t.talk(); t.work(); } }
(2)调试结果:
学生的姓名:张三 年龄:18 学号:0900104 学生正在回答老师的提问 学生的主要工作是学习 教师的姓名:lee 年龄:20教师号:2009001 老师正在讲课 教师的主要工作是教书育人