Java向上转型
1.向上转型
1.1 无重载情况
在平常的学习中,我们都知道继承是"is-a"关系,即子类属于超类的一,比如学生是人。我们一般都把学生和人两个类分别使用。如果我们把学生当作人来使用,就是向上转型。
public class FatherNewSon {
public static void main(String[] args) {
People people = new Student();
people.display();
System.out.println(people);
Student student = new Student();
people.display(student);
}
}
class People{
private String name;
private int age;
public People(){
name = "李华";
age = 18;
}
public void display(){
System.out.println("===People===");
}
public void display(People people){
people.display();
System.out.println(people);
}
@Override
public String toString() {
return "People{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
class Student extends People{
private String school;
public Student(){
school = "Tsinghua";
}
}
结果:
=== People===
People{name=‘李华’, age=18}
=== People===
People{name=‘李华’, age=18}
在上述代码中,我们进行了两次向上转型:一次是People people = new Student();
另一次是public void display(People people)
。从结果来看,两次转型是一样的:虽然用student转型为people,可还是只能调用people的功能,而不存在student类的特殊属性school,和用people没什么差异。
1.2 子类重载超类方法
看似向上转型没啥用处,这只是因为我们还没有对子类的方法进行重载。
public void display(){
System.out.println("===Student===");
}
如上,我们对超类的display()
进行重载,再运行一遍得到如下结果。
结果:
=== Student===
People{name=‘李华’, age=18}
=== Student===
People{name=‘李华’, age=18}
我们可以发现,此时转型之后调用的是子类的方法了。即如果子类没有重写超类方法,则向上转型后还是调用超类方法,如果重写了则调用子类的方法。
1.3 子类和超类有相同属性
//在student类加上如下代码
private String name;
//结果没有发生改变,说明在向上转型的时候,子类的属性被舍弃,保留了超类的属性。
1.4 子类的独有属性和方法
上面讲了子类和超类的共有方法、属性在子类重载之后的情况,下面来讲子类独有的属性和方法在向上转型之后还能否使用。
//在student中添加setter、getter
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getSchool() {
return school;
}
public void setSchool(String school) {
this.school = school;
}
//在main方法中视图调用子类方法,报错。
//System.out.println(people.setSchool);
答案是:子类独有属性与上述情况一致,都无法在转型之后传递给超类。这也符合逻辑,毕竟超类本来就没有这些属性。
2 总结
- 子类向上转型,子类特有属性无法向上传递,超类属性如果不进行操作,则超类对象的属性是初始值。但超类属性可以通过超类有参构造函数来进行更改初始值。
public Student(String name,int age){
super(name,age);
}
- 子类向上转型,子类独有的方法无法向上传递。而继承而来的方法如果被重写了,则调用的是子类的方法。尽管超类的私有方法在子类中重写,但还是会调用超类的方法。
- 在向上转型的时候,会先生成一个超类对象,然后再生成一个子类对象。
//在People类中添加:
public People(){
...
say();
}
private void say(){
System.out.println("hi");
}
//在Student类中添加:
public Student(){
say();
}
private void say(){
System.out.println("hello")
}
/*
结果:
hi
hello
*/