2.2.6 对象之间的类型转换
与基本数据类型之间的强制类型转换类似,在Java语言中,有继承关系的父类对象和子类对象之间也可以在一定条件下相互转换。父类对象和子类对象的转换需要注意以下原则:
(1)子类对象可以被视为是其父类的对象,反之则不可。
如B是A的子类,如下的用法是可以的:
A a = new B( );
也就是在使用的时候我们可以将用子类实例化的对象看成是父类的一个对象。但反过来,如下:
B b = new A( );
是不可以的。可以理解为,如果将父类和子类看做是两个杯子,子类可以容纳的细节更多,数据更多,相当于一个大杯子,而父类是个小杯子。我们可以将大杯子装小杯子的水也就是当成小杯子用,但是不可能将小杯子装大杯子的水当大杯子用。
(2)若父类对象引用指向的实际是一个子类对象(在以前的某个时候根据(1)规则将子类对象当成了父类对象用),则这个对象可以用强制类型转换还原成子类对象。如上面已经将子类B的对象当成了父类对象用了,相当于在大杯子上贴了个标签说它是小杯子,现在我们可以重新给它贴上大杯子的标签,还原它本来的面目。
A a = new B( ); B b = ( B )a;//还原成子类对象
【例2-9】 类对象之间的类型转换的应用。
class SuperClass{ // 父类 int a=5,b=8; void show(){ System.out.println("执行父类SuperClass"); } } class SubClass extends SuperClass{ // 子类 int b=10; void show(){ System.out.println("执行子类SubClass"); } } public class ClassExchangeDemo { public static void main(String[] args) { SuperClass super1,super2; // 声明两个父类对象 SubClass sub1,sub2; // 声明两个子类对象 super1=new SuperClass(); // 实例化第一个父类对象 System.out.println("super1.a="+super1.a+" super1.b="+super1.b); super1.show(); sub1=new SubClass(); // 实例化第一个子类对象 System.out.println("sub1.a="+sub1.a+" sub1.b="+sub1.b); sub1.show(); super2=sub1; // 根据原则(1):子类对象视为父类对象 System.out.println("super2.a="+super2.a+" super2.b="+super2.b); super2.show(); sub2=(SubClass)super2; // 根据原则(2):父类对象强制转换为子类对象 System.out.println("sub2.a="+sub2.a+" sub2.b="+sub2.b); sub2.show(); } }
该程序的运行结果如下:
super1.a=5 super1.b=8 执行父类SuperClass sub1.a=5 sub1.b=10 执行子类SubClass super2.a=5 super2.b=8 执行子类SubClass sub2.a=5 sub2.b=10 执行子类SubClass
工作分解-操作方案
1.分析抽象出类;
2.按照类图编制出类框架;
3.实现类方法;
4.创建对象;
5.调用对象中的方法完成功能。
工作实施
1.分析抽象出类
从本任务中,可以分析出共有三个类:People类是父类,Student类和Teacher类都是People类的子类。People类有三个非私有属性:姓名name、年龄age和默认值为“工人”的身份id;三个公有成员方法:一个带参构造方法,用于初始化属性值,一个表示“人”说话行为的方法talk(),以及表示“人”工作行为的方法work()。Student类除了从父类People继承的成员外还新增了一个属性:学号sNo;Teacher类除了从父类People继承的成员外还新增了一个属性:教师号tNo。
在UML中,继承关系用一条从子类指向父类的空心三角箭头表示,如图2-6所示。
图2-6 人(People)、学生(Student)和教师(Teacher)类图及关系
2.按照类图编制出类框架
/** *"人"类(是学生类和教师类的父类) */ class People { String name; // 姓名 int age; // 年龄 String id="工人"; // 默认身份 public People(String name,int age){ // 构造方法 } public void talk(){ // 说话行为 } public void work(){ // 工作行为 } } /** * 学生类,派生自People类 */ class Student extends People{ // 构造方法 String sNo; // 学号 String id="学生"; // 身份,父类同名的成员变量被隐藏 public Student(String name,int age,String sNo){ // 构造方法 } } /** * 教师类,派生自People类 */ class Teacher extends People { String tNo; // 教师号 String id="教师"; // 身份,父类同名的成员变量被隐藏 public Teacher(String name,int age,String tNo){ // 构造方法 } }
3.实现类中的方法
// 实现People类中的方法 public People(String name,int age){ // 构造方法 this.name = name; this.age = age; } public void talk(){ // 说话行为 System.out.println(name+"能说话"); } public void work(){ // 工作行为 System.out.println(name+"能工作"); } // 实现Student类中的方法 public Student(String name,int age,String sNo){ // 构造方法 super(name,age); // 调用直接父类的构造方法 this.sNo = sNo; } // 实现Teacher类中的方法 public Teacher(String name,int age,String tNo){ // 构造方法 super(name,age); // 调用直接父类的构造方法 this.tNo = tNo; }
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("学生信息:"); System.out.println("name = " + s.name + ", age = " + s.age + ", sNo = " + s.sNo + ", id = " + s.id); s.talk(); // 该方法继承于父类 s.work(); // 该方法继承于父类 // 打印教师信息 System.out.println("教师信息:"); System.out.println("name = " + t.name + ", age = " + t.age + ", tNo = " + t.tNo + ", id = " + t.id); t.talk(); // 该方法继承于父类 t.work(); // 该方法继承于父类
7.代码调试并运行
(1)完整源代码如下:
class People { String name; // 姓名 int age; // 年龄 String id="工人"; // 身份 public People(String name, int age) { this.name = name; this.age = age; } public void talk(){ // 说话行为 System.out.println(name+"能说话"); } public void work(){ // 工作行为 System.out.println(name+"能工作"); } } /** * 学生类,派生自People类 */ class Student extends People{ // 构造方法 String sNo; // 学号 String id="学生"; // 身份,父类同名的成员变量被隐藏 public Student(String name,int age,String sNo){ // 构造方法 super(name,age); // 调用直接父类的构造方法 this.sNo = sNo; } } /** * 教师类,派生自People类 */ class Teacher extends People { String tNo; // 教师号 String id="教师"; // 身份,父类同名的成员变量被隐藏 public Teacher(String name,int age,String tNo){ // 构造方法 super(name,age); // 调用直接父类的构造方法 this.tNo = tNo; } } public class Test { public static void main(String[] args) { Student s = new Student("张三", 18, "0900104"); System.out.println("学生信息:"); System.out.println("name = " + s.name + ", age = " + s.age + ", sNo = " + s.sNo + ", id = " + s.id); s.talk(); s.work(); Teacher t = new Teacher("lee", 20, "2009001"); System.out.println("教师信息:"); System.out.println("name = " + t.name + ", age = " + t.age + ", tNo = " + t.tNo + ", id = " + t.id); t.talk(); t.work(); } }
(2)调试结果:
学生信息: name= 张三,age=18,sNo=0900104,id= 学生 张三能说话 张三能工作 教师信息: name=lee,age=20,tNo=2009001,id= 教师 lee能说话 lee能工作