多态的唯一目的就是实现所谓的“动态绑定”。
什么叫动态绑定?
除了限制访问,访问方式也决定哪个方法将被子类调用或哪个属性将被子类访问. 函数调用与函数本身的关联,以及成员访问与变量内存地址间的关系,称为绑定。若在程序执行前进行绑定(例如编译期)的话,叫做前期绑定,或静态绑定,但是它不能利用任何运行期的信息(c语言c++语言都是前期绑定)。相应的,在运行时候根据对象的类型进行绑定叫后期绑定,也叫动态绑定。也就是说,如果一个语言想实现后期绑定,就必须具有某种机制,以便能够在运行时能判断对象的类型,从而调用恰当的方法。动态绑定的好处是允许继承类来改变父类的行为,同时可以保持父类的接口和功能。
在java中,除了static方法和final方法(private方法属于final方法)之外,其他的都默认进行后期绑定(就是可以多态)。如果将一个方法声明为final或者static或者private,就告诉编译器不需要对该方法动态绑定。这样,编译器就可以可以为final方法调用生成更有效的代码()。
类的一个成员若想表现多态必须可以被覆盖:
对于成员变量而言,不会发生覆盖现象(会隐藏),在子类出现相同变量的定义时只会隐藏父类变量,因此不会表现多态。同时变量调用在编译时就会解析,不符合动态绑定的特征;
在成员方法中,静态方法和final方法(private方法)也不会发生覆盖现象(会隐藏),因此也不会表现多态性。只有除静态方法和final方法以外的方法才会表现多态性。
例子:
class Base{
public int a=2;
public void method(){
System.out.println("base:method");
}
int getA(){
return a;
}
}
class Sub extends Base{
public int a=3;
public void fmethod(){
System.out.println("sub:method");
}
//子类方法可视范围可以扩大
public int getA(){
return a;
}
}
public class Test {
public static void main (String args []) {
Base b=new Sub();
//方法多态,输出sub:fmethod
b.fmethod();
//属性不能多态,输出为2.
System.out.println(b.a);
//但是可以通过方法来实现属性的多态,输出3
System.out.println(b.getA());
}
}