java的多态中有个值得注意的地方那就是转型,其中向下转型虽然不安全但是却相当重要(运用的地方比安全的向上转型还多),所以为了后面学习框架预热,我们先来做一下转型的实验,磨刀不误砍柴功嘛,在这之前,先简略的介绍一下继承
继承是从已有的类中派生出新的类,新的类能吸收已有类的数据属性和行为,并能扩展新的能力。
java继承的特性:
(1)继承关系是传递的。继承是在一些比较一般的类的基础上构造、建立和扩充新类的最有效的手段。
(2)继承简化了人们对事物的认识和描述,能清晰体现相关类间的层次结构关系。
(3)继承提供了软件复用功能,能减小代码和数据的冗余度,大大增加程序的重用性。
(4)继承通过增强一致性来减少模块间的接口和界面,大大增加了程序的易维护性。
继承修饰符为extends,格式为CLASS A EXTENDS ANOTHERCLASS,后者是前者的父类(如果事先学过CPP应该不难掌握)
关于类内代码的执行顺序可以参考我原先写过的java类中代码执行顺序
闲话不多说进入正题,我们首先来讲的是向上转型,其核心思想是子类继承了父类,也就是说子类拥有父类全部的特性(尽管你添加或者重写了方法和覆盖了属性)。比如一个男人类,他的父类是人类,而男人类拥有所有人类的行为,我们可以说男人是人。而向上转型就是这么一种类似的关系。我们先假定存在一个父类,并在父类中定义一个show方法和一个检测方法test2,在子类重写这个show并且添加一个检测方法test,我们得到下面的代码:
package FOREXTENDS;
class theParent {
public void test2(){
}
public void SHOW(){
System.out.println("父类的方法成功执行!");
}
}
public class theChild extends theParent{
@Override
public void SHOW(){
System.out.println("子类的方法成功执行!");
}
public void test(){
}
static public void main(String[] args ){
theParent child= new theChild();
child.SHOW();
child.test2();
}
}
上述代码中如果test2改为test程序会报错,并且显示出来的show是子类的。这是因为我们实际上new的是子类,也就是实际的使用空间是子类的,因此我们对子类进行调用,而由于继承,你能够使用父类的方法。这里要注意的是,因为声明的是父类,所有在子类新增的属性和方法是无法被使用的。(推出结论:你可以使用父类的所有方法,但如果是父类和子类重合的部分,我们使用子类的)
正由于这样我们还能像int自动转成double一样,子类也可以在一定场合自动转化为父类(隐性转型)
package DRAW;
class Quadrangle{
public static void draw(Quadrangle q){
}
}
public class Parallelogram extends Quadrangle {
public static void main(String args[]){
Parallelogram p= new Parallelogram();
draw(p);
}
}
这里面我们通过调用父类的方法将子类转化成了父类。
那么接下来就是向下转型,关于这点,我觉得有必要先讲述向下转型的意义。首先向下转型是不安全的,你可以说男人是人,但你不能说所有的人都是男人,这是错误的。程序中由于子类拥有很多父类没有的属性和 方法。因此程序编译是不会默认通过向下转型的就像编译不会默认通过double类型的值赋给int一样,所以我们要通过类似强制转换的方法得到想要的答案
package FOREXTENDS;
public class Parent {
public void test1(){
}
public void SHOW(){
System.out.println("父类的方法成功执行!");
}
static public void main(String[] args ){
Child parent=(Child) new Parent();
parent.test();
parent.test1();
parent.SHOW();
}
}
class Child extends Parent{
public void SHOW(){
System.out.println("子类的方法成功执行!");
}
public void test(){
}
}
这个代码看上去没有问题但实际上并不是这样,我们编译通过后进行运行,控制台会报错:
为了探究真相,我重新定义了一个包并且修改了主要类发现问题仍然存在,那么主要原因不是这个,接下来我取消了测试类,发现仍然存在错误。那么应该是向下转型的过程中出现了问题,他的报错是这个类不能这样转型,之后我选择了先向上转型,再向下转型的方式,编译通过,并能调用父类和子类的方法,如下
package ROR;
class Parent {
public void test1(){
System.out.println("这里是父类方法测试!");
}
public void SHOW(){
System.out.println("父类的方法成功执行!");
}
}
public class Child extends Parent{
public void SHOW(){
System.out.println("子类的方法成功执行!");
}
public void test(){
System.out.println("这里是子类方法测试");
}
static public void main(String[] args ){
Parent parent= new Child();
Child pa=(Child)parent;
pa.SHOW();
pa.test1();
pa.test();
}
}
附加运行截图:
这是因为向上转型使用的是子类空间,所以向下转型的时候能够成功,所经历的的是子类到父类到子类,这之中我们的对象获得了子类和父类的全部方法(重合的部分使用子类),其实也能够用白话去解释,那就是他原本就是男人,不可能说他是人之后,他就会不是男人了