Java 继承与多态之转型
向上转型:将子类的对象赋值给父类引用
向下转型:将父类的对象赋值给子类引用(前提是父类对象必须能够转成子类对象)
1、向上转型:
public class Person
{
public String name;
public int age = 30;
public void work()
{
System.out.println("工作");
}
public void eat()
{
System.out.println("在食堂吃饭");
}
}
public class Student extends Person
{
public int age = 20;
public void study()
{
System.out.println("学习");
}
public void eat()
{
System.out.println("在学生食堂吃饭");
}
}
Person p = new Student(); //向上转型:将子类 Student 的对象赋值给父类 Person 引用 p
注意:一个引用能够调用哪些成员(成员变量和成员方法)取决于这个引用拥有的哪些成员,而不是引用的对象所拥有的成员。换句话说,多态中访问变量时,使用的是父类的成员(成员变量和成员函数),而方法存在重写,所以调用的是子类的方法(静态方法除外)
System.out.println(p.age) 打印的是Person的成员变量age的值:30
p.eat() 打印的是:在学生食堂吃饭,这是因为子类 Student 重写了父类 Person 的 eat() 方法
p.study() 报错,因为在 Person 类并不存在 study() 方法,所以调用出错。这个就是多态的弊端:只能使用父类定义过的方法,不能够使用子类的特有方法
为什么用向上转型:
如果还有一个 Teacher 类也继承了 Person 类,并且重写了 eat() 方法,即:
public class Teacher extends Person
{
public void eat()
{
System.out.println("在教师食堂吃饭");
}
}
然后存在如下构成重载的方法
public void method(Student s)
{
s.eat();
}
public void method(Teacher t)
{
t.eat()
}
如果 Person 的子类有很多,那么就会有很多的类似的代码,如果一旦涉及到代码修改就是一个非常头疼的问题,而这个时候就可以用向上转型来解决这个问题:
public void method(Person p)
{
p.eat();
}
这样 method() 方法就可以传入任意 Person 的子类了,而且就算修改也只需要修改一个地方就行了
2、向下转型
向上转型的时候提到了一个弊端:只能使用父类定义过的方法,不能够使用子类的特有方法。如果一定要使用子类的特有方法(如 Student 对象的 study() 方法),又该怎么办呢?
既然 Study() 方法是 Student 对象特有的方法,那么我们只需要得到一个 Student 对象就行了,关键是如何得到呢?
1、Student s = new Student();
s.study();
毫无疑问,这样做没有任何问题,但是这不是我们想要的效果。
2、Student s = (Student) p; //向下转型:将父类的对象赋值给子类引用(前提是父类对象必须能够转成子类对象)
s.study();
这样就好多了,因为不会像 1 中一样多生成一个Student对象造成内存浪费
注意:
1、Student s = new Person() 这种做法是错误的;
2、Person p1 = new Teacher(); Student s1 = (Student) p1 也是错误的,因为 p1 不能够转成 Student 对象
3、向上转型必须先向下转型;