向上转型
- 经典案例
- 向上转型
- 向上转型应留神的问题
- 向上转型的益处
- 静态方法的调用
经典案例
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办法。