多态
一、什么是多态?
多态通过分离做什么和怎么做,从另一个角度将接口和实现分离开来。如果说封装是通过合并特征和行为来创建新的数据类型,“实现隐藏”则是通过细节“私有化”把接口和实现分离开来。多态的作用则是消除了类型之间的耦合关系。多态方法调用允许一种类型表现出与其他相似类型之间的区别。只要他们都是从同一个基类继承而产生的。
二、.向上转型是?
对象既可以作为它自己本身的类型使用,也可以作为它的基类型使用。把这种对某个对象的引用视为对其基类型的引用的做法被称作为向上转型,因为在继承树的画法中,基类是放在上面的。
public class Instrument{ public void play(){ System.out.println(" instrment play"); } } public class Brass extends Instrument{ public void play(){ System.out.println("brass play"); } }
对于Instrument i=new Brass();不需要类型转换,这样做是允许的,因为Brass从Instrument继承而来,所以instrument的接口必定存在于Brass中。
三、多态的实现原理?
方法调用绑定:将一个方法调用同一个方法主体关联起来称为绑定。如果是在程序执行前进行绑定(由编译器和连接程序实现),叫做前期绑定,它是面向过程的语言不需要选择就默认的绑定方式。c语言只有一种方法调用,那就是前期绑定。向上转型之所以令人困惑,主要是因为前期绑定,当编译器只有一个instrument引用时,它无法知道究竟调用那个方法才对。解决的方法是后期绑定,它的含义就是运行的时候根据对象类型进行绑定。后期绑定也可以称作动态绑定或运行时绑定,如果一种语言想要实现后期绑定,就必须具有某种机制,以便在运行时能判断对象的类型,从而调用恰当的方法。也就是说,编译器一直不知道对象的类型,但是方法调用机制能找到正确的方法体,并加以调用,后期绑定机制随着编程语言的不同而有所不同,但是不管怎样都必须在对象中安置某种类型信息。java中除了static方法和final方法(private方法属于final方法)之外,其他所有的方法都是后期绑定。为什么将某个方法声明为final?这样做不仅可以防止其他人覆盖该方法,也可以有效地关闭动态绑定。
四、多态的缺陷?
1.覆盖私有方法:
public class PrivateOverride{ private void f(){ System.out.println("private f()"); } public static void main(String[] args){ PrivateOverride po=new Derived(); po.f(); } } public class Derived extends PrivateOverride{ public void f(){ System.out.println("public f()"); } } //output:private f()
由于private方法自动认为是final方法,而且对子类是屏蔽的,在这种情况下,derived类中的f方法就是一个全新的方法,也不能被重载。只有非private方法才可以被覆盖。
2.域和静态方法
public class Super{ public int field=0; public int getFiled(){ return this.field; } } public class Sub extends Super{ public int field=1; public int getFiled(){ return this.field; } public int getSuperField(){ return super.getFiled; } } public class FieldAccess{ public static void main(String[] args){ Super sup=new Sub(); System.out.println(sup.field+" "+sup.getFiled());//0 1 Sub s=new Sub(); System.out.println(s.field+" "+s.getFiled()+" "+s.getSuperField());//1 1 0 } }
向上转型的时候,任何域访问操作都将由编译器解析,因此不是多态的。如果某个方法是静态的,他的行为就不具有多态性,静态方法是与类,而并非与单个对象相关联的。