------- android培训、java培训、期待与您交流! ----------
多态:事物之间存在多种体现形态
1、多态的体现
父类引用指向子类对象,父类引用也可以接受自己的子类对象。这么做的好处是提高了程序的扩展性,但是使用多态的前提是存在继承或实现。
下面的代码是父类引用接收子类对象:
class Cycle{
private String name;
public Cycle(){
}
public String toString(){
return name + " ";
}
}
class Unicycle extends Cycle{
private String name;
public Unicycle(String name){
this.name = name;
}
public String toString(){
return name + " ";
}
}
class Bicycle extends Cycle{
private String name;
public Bicycle(String name){
this.name = name;
}
public String toString(){
return name + " ";
}
}
class Tricycle extends Cycle{
private String name;
public Tricycle(String name){
this.name = name;
}
public String toString(){
return name + " ";
}
}
public class DuoTai {
public static void ride(Cycle c){
System.out.println(c.toString() + "riding");
}
public static void main(String[] args){
Unicycle u = new Unicycle("unicycle");
Bicycle b = new Bicycle("bicycle");
Tricycle t = new Tricycle("tricycle");
ride(u);
ride(b);
ride(t);
}
}
这样做的好处是,如果以后要继承出新的Cycle子类,我们不需要重载ride()方法,省去了大量不必要的工作。
2、动态绑定
动态绑定又叫做运行时绑定,就是在运行时根据对象的类型进行绑定。在编译时期,编译器不知道对象类型,但方法调用机制能够找到正确的方法体。
Java中除了static和final方法之外,都是动态绑定。
3、多态中成员函数的特点:
1) 对于非静态的成员函数,在编译期间,参阅引用型变量所属的类中是否有调用的方法,如果有,编译通过,没有则编译失败。运行期间,参阅对象所属的类中是否有调用的方法。
即编译看左边,运行看右边。
2)对于静态的成员函数,无论编译还是运行,都参考左边。
3)对于成员变量,无论是静态还是非静态,都参考左边。
class Rodent{
public void eat(){
System.out.println("Rodent.eat()");
drink();
}
public void drink(){
System.out.println("Rodent.drink()");
}
}
class Mouse extends Rodent{
public void drink(){
System.out.println("Mouse.drink()");
}
}
public class DuotaiTest {
public static void main(String[] args){
Rodent m = new Mouse();
m.eat();
}
}
因为多态中 Rodent m = new Mouse();父类指向了子类对象,也就是说将子类对象提升为了父类对象。
m.eat(); 提升为父类对象后,调用eat()方法。因为父类中也定义了eat()方法,所以编译通过,如果父类中没有定义该方法,就会编译失败。即所谓的编译看左边,左边即父类。
因为m被提升为父类对象,m.eat()也是调用父类中的方法,但是为什么输出的是Mouse.drink()而不是Rodent.drink()。
原因很简单,因为子类中也定义了同名的drink()方法,发生了函数的覆盖,子类覆盖了父类中的同名函数,所以运行的是子类的函数,也就是所说的运行看右边,因为右边是子类。