乐趣区

关于java:java之向上转型神解析

向上转型

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

经典案例

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 办法。

退出移动版