向上转型

  • 经典案例
  • 向上转型
  • 向上转型应留神的问题
  • 向上转型的益处
  • 静态方法的调用

经典案例

public class Animal {    public void eat(){        System.out.println("animal eatting...");    }}public class Cat extends Animal{    public void eat(){        System.out.println("我吃鱼");    }}public class Dog extends Animal{    public void eat(){        System.out.println("我吃骨头");    }    public void run(){        System.out.println("我会跑");    }}public class Main {    public static void main(String[] args) {        Animal animal = new Cat(); //向上转型        animal.eat();        animal = new Dog();        animal.eat();    }}//后果://我吃鱼//我吃骨头

当父类对象援用变量援用子类对象时,被援用对象的类型决定了调用谁的成员办法,援用变量类型决定可调用的办法。Animal是援用变量类型,它决定哪些办法能够调用;eat()办法能够调用,而cat是被援用对象的类型,它决定了调用谁的办法:调用cat的办法。

向上转型

  • 子类援用的对象转换为父类类型称为向上转型。艰深地说就是是将子类对象转为父类对象。此处父类对象能够是接口。
  • Animal animal = new Cat();将子类对象Cat转化为父类对象Animal。这个时候animal这个援用调用的办法是子类办法。

向上转型应留神的问题

  • 向上转型时,子类独自定义的办法会失落。比方下面Dog类中定义的run办法,当animal援用指向Dog类实例时是拜访不到run办法的,animal.run()会报错。
  • 子类援用不能指向父类对象。Cat c = (Cat)new Animal()这样是不行的。

    Fu f=new Zi();

1、将子类对象赋值给父类对象,父类对象就成了子类的上转型对象,然而这只能拜访从父类继承的办法和变量或者重写的办法。
2、只能让上转型对象调用(拜访)子类中与父类无关的成员,子类中本人后定义的成员不能被调用(变量或办法)

向上转型的益处

  • 缩小反复代码,使代码变得简洁。
  • 进步零碎扩展性。
    举个例子:比方我当初有很多品种的动物,要喂它们吃货色。如果不必向上转型,那我须要这样写:
public void eat(Cat c){    c.eat();}public void eat(Dog d){    d.eat();}//......eat(new Cat());eat(new Cat());eat(new Dog());//......

一种动物写一个办法,如果我有一万种动物,我就要写一万个办法,写完大略猴年马月都过了好几个了吧。好吧,你很厉害,你耐着性子写完了,认为能够放松一会了,忽然又来了一种新的动物,你是不是又要独自为它写一个eat办法?开心了么?
那如果我应用向上转型呢?我只须要这样写:

public void eat(Animal a){    a.eat();}eat(new Cat());eat(new Cat());eat(new Dog());//.....

恩,搞定了。代码是不是简洁了许多?而且这个时候,如果我又有一种新的动物加进来,我只须要实现它本人的类,让他继承Animal就能够了,而不须要为它独自写一个eat办法。是不是进步了扩展性?

class Fuc{    public int num=100;    public void show(){        System.out.println("show Fuc");    }}class Zic extends Fuc{    public int num=1000;    public int num2=200;    @Override    public void show() {        System.out.println("show Zic");    }}public class DuoTai {    public static void main(String[] args) {        Fuc f=new Zic();        System.out.println(f.num);        //System.out.println(f.num2);  编译谬误        f.show();    }}

编译器在编译阶段会先看父类,编译器通过申明对象的类型(即援用自身的类型)在办法区中该类型的办法表中查找匹配的办法。所以起初父类中没有num2变量,你用父类的援用去拜访子类的变量编译不会通过,子类能够拜访父类,然而父类不能拜访子类,因为子类继承了父类。艰深点说就是儿子能够拜访父亲,然而你父亲不能拜访儿子。

静态方法的调用

class A {public static void show(){        System.out.println("hhhh");    }}class B extends A {    public static void show(){        System.out.println("你哈");    }}public class C{    public static void main(String[] args) {        A b=new B();        b.show();    }}

静态方法不具备多态性,因为
动态和类相干,和对象实例无关,静态方法能够继承和重写,但重写只是模式上的(算不上重写),父类办法并没有被笼罩掉。同名将暗藏。静态方法是被暗藏而不是被笼罩,所以上转型变量调用这个静态方法时,调用的是子类中继承的并且被暗藏的static办法,深层次去了解就是静态方法属于动态绑定,在编译过程中,办法与援用变量类型绑定,编译器看的是父类,所以运行时以申明类型为准,上转型变量调用的是继承且被暗藏的static办法。