java向上转型

向上转型:将子类对象的引用转换为父类对象的引用,这就是向上转型。

”为新的类提供方法“这并不是继承中最重要的方面,其最重要的是用来表现新类和基类之间的关系。这种关系是”新类是现有类的一种类型“ 也就是is-a。例如:假设有一个称为Animal的代表动物的类和一个称为dog的导出类。继承可以保证基类中的所有的可继承方法(除了私有方法,不同包情况下的包访问权限方法)在导出类中也同样有效,所以能向基类发送的信息同样也可以向导出类发送。如:Animal有一个public的eat()方法,那么dog类也将具有此方法。这也就意味着dog对象也是一种类型的Animal。看一个例子:

class Animal {
    public void eat(){}
    static void tune(Animal a){
        //....
        a.eat();
    }
}

public class Dog extends Animal{
    public static void main(String[] args){
        Dog hashiqi = new Dog();
        Animal.tune(hashiqi);  //向上转型
    }
}

在此例中,tune()方法可以接受Animal的引用,但在Dog.main()方法中,传递给tune方法的是一个Dog引用。刚开始我也不懂这到底是怎么回事,以为代码写错了呢。在tune()中,程序代码可以对Animal和它所有的导出类起作用,这将Dog引用转换为Aniaml引用的动作,就是向上转型。

2  为什么称为向上转型
传统的类继承图:基类置于页面的顶端,然后导出类逐渐向下。由导出类转型成基类,在继承图上是向上移动的,因此一般称为向上转型。
导出类是基类的一个超集。它可能比基类含有更多的方法,但它必须至少具备基类中的所有方法。在向上转型的过程中,类接口唯一可能发生的事情就是丢失方法,而不是获取它们。

3  再论向上转型
向上转型可以这么写: Shape s  =  new  Circle();创建了一个Circle对象,并把他的引用赋值给Shape,看起来是错误的但是由于继承,Circle也是一种Shape,因此没有问题。
java向上转型_第1张图片
示例:
public class Shape {
    public void draw(){System.out.println("Shape.draw()"}
    public void earse(){System.out.println("Shape.earse()"}
}

public class Square extends Shape{
    public void draw(){System.out.println("Square.draw()"}
    public void earse(){System.out.println("Square.earse()"}
}

public class Circle extends Shape{
    public void draw(){System.out.println("Circle.draw()"}
    public void earse(){System.out.println("Circle.earse()"}
}

public class Triangle extends Shape{
    public void draw(){System.out.println("Triangle.draw()"}
    public void earse(){System.out.println("Triangle.earse()"}
}

public class Test{
    public static void main(String[] args){
        Shape s = new Circle();
        s.draw();
        s.erase();
    }
}
输出:
Circle.draw()
Circle.earse()
以前,我认为输出的答案应该是Shape.draw() Shape.earse().但是结果并不是那样。Shape s = new Circle();中的s是父类的引用,指向的确是子类的对象,编译器在执行的时候会先找子类对象中的方法,如果子类中由这个方法就会调用子类中的方法,如果没有才会查看父类中是否有这个方法。之所以能正确将引用指向Circle而不是Square或Triangle,是因为后期绑定。

4  域与静态方法
向上转型时调用域,会有什么样的结果呢,请往下看:
示例:
class Super{
    public int field = 0;
    public int getField(){ return field;}
}

public class Sub extends Super{
    public int field = 1;
    public int getField(){ return field;}
    public int getSuperField{return super.field;}  //显示调用父类的域
    public static void main(String[] args){
        Super sup = new Sub();      //向上转型
        System.out.println("sup.field="+sup.field+", sup.getField()="+sup.getField());
        Sub sub = new Sub();     //没有向上转型
        System.out.println("sub.field="+sub.field+", sub.getField()="+sub.getField()+", sub.getSuperField()="+sub.getSuperField());
    }
}
输出:
sup.field=0, sup.getField()=1;
sub.field=1, sub.getField()=1, sub.getSuperField()=0;

当Sub对象转型为Super引用时,任何域访问操作都将由编译器解析,因此不是多态的,所以sup.field调用的是父类的field。当引用Sub要访问父类的域时,需要显示的指明super.field。

再看一个例子:
class Super{
    public static String staticGet(){
        return "base class staticGet()";
    }
    public String dynamicGet(){
        return "base class dynamicGet()";
    }
}

public class Sub extends Super{
    public static String staticGet(){
        return "export class staticGet()";
    }
    public String dynamicGet(){
        return "export class dynamicGet()";
    }
    public static void main(String[] args){
        Super sup = new Sub(); //向上转型
        System.out.println(sup.staticGet());
        System.out.println(sup.dynamicGet());
    }
}
输出:
base class staticGet()
export class dynamicGet()
有输出结果可以看出,静态方法不具有多态性,静态方法是与类,而非单个对象相关联的。

你可能感兴趣的:(java,父类,子类,向上转型)