Java多态:
不修改程序代码就可以改变程序运行时所绑定的具体代码,让程序可以选择多个运行状态,即所谓的多态性。
- 多态实现的三个必要条件:继承,方法重写,向上转型;
- 多态机制应该遵循:
当超类对象引用变量引用子类对象时,即为向上转型,编译时变量类型由“=”左边(超类)决定,运行时类型由“=”右边(子类)决定,此时调用的方法是子类覆盖或者继承父类的方法。通过父类引用变量无法调用子类独有的方法。
-
实现形式:继承和接口;
-
经典案例:
该实例是有关多态的经典例子,摘自:http://blog.youkuaiyun.com/thinkGhoster/archive/2008/04/19/2307001.aspx。
class A{
public void show(D obj){
System.out.println("A and D");
}
public void show(A obj){
System.out.println("A and A");
}
}
class B extends A{
public void show(B obj){//方法重载
System.out.println("B and B");
}
public void show(A obj){//方法重写
System.out.println("B and A");
}
}
class C extends B{
}
class D extends B{
}
public class Test {
public static void main(String[] args){
A a1 = new A();
A a2 = new B();
B b = new B();
C c = new C();
a1.show(b);
a1.show(c);
a2.show(b);
a2.show(c);
}
}
运行结果:
A and A
A and A
B and A
B and A
分析:
a1.show(b);和a1.show(c);容易理解:a1是A的对象,在A中调用对应方法,b是类B对象,但参数列表无对应参数,而B继承于A,找其父类,故调用A中的show(A obj)方法,返回"A and A";a1.show(c)也是同样的道理;
对于a2.show(b);a2是类B的对象,应该调用类B中的show方法,应该调用B中的show方法,返回"B and B",但是最后的结果表明,调用的是类B中的show(A obj)方法,返回"B and A",这是为什么???其实在继承链中也有调用方法的优先级顺序:this.show(o)-->super.show(o)-->this.show(super(o))-->super.show(super(o));所以,优先调用this.show(o),此处的this为类A,参数类型为B,表明类A中没有该方法,而super.show(o),由于A没有父类(Object除外),跳到this.show(super(o)),B继承于A,super(o)为A,即this.show(A o),在A中找到了show(A obj)方法,而B为A的子类,重写了该方法,即A中的该方法被覆盖了,故调用了B中方法,返回"B and A";对于a1.show(c),也是同样的道理。
-
总结:
- 对于多态,由于指向子类的父类引用向上转型,只能访问父类中的属性和方法,对于子类中存在而父类中不存在的方法,它是不能访问的;子类重写了父类中的某些方法,在调用该方法时,必须调用子类中的这些方法;
- 就面向对象而言,多态分为编译期多态和运行期多态,编译期多态(静多态),主要指方法重载,根据参数列表不同来区分不同的方法,编译后变成两个不同的方法,运行时谈不上多态;而运行期多态(动多态),主要指动态绑定实现,也就是我们所说的"多态性"。