共计 2333 个字符,预计需要花费 6 分钟才能阅读完成。
向上转型
- 经典案例
- 向上转型
- 向上转型应留神的问题
- 向上转型的益处
- 静态方法的调用
经典案例
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 办法。