上下转型
首先,定义一个父类Person
// 父类
class Person {public void run(){System.out.println("person 中的 run");}public void eat(){System.out.println("Person 中的 eat");}}
接着定义一个继承自父类的子类Student:
// 子类
class Student extends Person {// 重回了父类中的run方法@Overridepublic void run() {System.out.println("Student 中的 run");;}// 父类中没有的子类特有的方法public void study(){System.out.println("Student 中独有的study");}
}
ok, 现在开始说明什么是向上转型和向下转型:
public class homework11 {public static void main(String[] args) {// 向上转型,子 -> 父, p1实际上仍然是一个Student方法,可以通过p1.getClass()查看,但是只能调用Person公开的方法Person p1 = new Student();p1.run(); // run是p1公开的方法,所以可以调用,但是记住调用的是子类中的run,因为p1实际上就是一个Student类p1.eat(); // 调用子类中的eat,子类中没有重写该方法,虽然结果是“Person 中的 eat”,但是仍然是调用的子类中的该方法// p1.study() // 报错,只能调用父类中已经声明了的方法// 向下转型// 报错,父类对象不能隐式的转换成子类,要想转换必须显示的声明,这相当于告诉编译器我就是故意的,我愿意承担由此导致的问题// Student s1 = new Person();// Student s1 = (Student) new Person(); // 仍然报错,因为这里匿名创建的new Person() 对象并不是Student类型// 乍一看跟上面一样是将Person类转成了Student,但是并没有报错,因为这里的p2实际上是一个Student类,因为p2是Student向上转型得到的Person p2 = new Student();Student s2 = (Student) p2; // 这里又转回去了,这没啥好说的,相当于 Student s2=new Student();}
}
关于多态
上面的向上转型就是多态的过程,表现为虽然都是Person类型但是实际调用的确实不同的子类自己重新重写的方法。最典型的应用就是函数的参数是父类,传进来的是不同的子类,这样函数内部调用父类的方法时实际运行的是子类重构过的方法。
为了方便说明,这里再定义一个继承自上面Person类的Teacher类:
public class Teacher extends Person{@Overridepublic void run() {System.out.println("Teacher 中的run");;}
}
ok,具体使用时是这样的:
public class homework11 {static void f(Person pp){pp.run();}public static void main(String[] args) {Person p1 = new Student();Person p2 = new Teacher();f(p1);// 调用Student类中的run方法f(p2); // 调用Teacher中的run方法}
}
这种操作的优点就是,虽然f()中的代码已经写死了,但是实际运行过成中具体调用的方法仍然是可以根据传进来的子类的不同而发生改变的!