以下摘自《Java编程思想》
在面向对象的程序设计语言中,多态是继续数据抽象和继承之后的第三种基本特征。
多态通过分离做什么和怎么做,从另一角度将接口和实现分离开来。多态不但能够改善代码的组织结构和可读性,还能够创建可扩展的程序---即无论在项目最初创建时还是在需要添加新功能时都可以“生长”的程序。多态也被称作动态绑定,后期绑定或运行时绑定。
java中除了static方法和final防止(private方法属于final方法)之外,其他所有的方法都是后期绑定。
1、域与静态方法
public class Super { public int field = 0; public int getField (){ return field; } }
public class Sub extends Super { public int field = 1; public int getField (){ return field; } public int getSuperField (){ return super.field; } }
public class FieldAccess { public static void main(String[] args) { Super sup = new Sub(); System.out.println("sup.field="+sup.field+"-sup.getField()="+sup.getField()); Sub sub = new Sub(); System.out.println("sub.field="+sub.field+"-sub.getField()="+sub.getField()+"--sub.getSuperField="+sub.getSuperField()); } }
sup.field=0-sup.getField()=1 sub.field=1-sub.getField()=1--sub.getSuperField=0
如果某个方法是静态的,它的行为就不具有多态性:
public class StaticSuper { public static String staticGet(){ return "Base staticGet()"; } public String dynamicGet(){ return "Base dynamicGet()"; } }
public class StaticSub extends StaticSuper { public static String staticGet() { return "Dervied staticGet()"; } public String dynamicGet() { return "Dervied dynamicGet()"; } }
public class StaticPolymorphism { public static void main(String[] args) { StaticSuper sup = new StaticSub(); System.out.println(sup.staticGet()); System.out.println(sup.dynamicGet()); } }
2、构造器多态
构造器不具有多态性(她们实际上市static方法只不过该static声明是隐式的)。
public class Glyph { void draw(){ System.out.println("Glyph.draw()"); } Glyph(){ System.out.println("Glyph() before draw()"); draw(); System.out.println("Glyph() after draw()"); } }
public class RoundGlyph extends Glyph { private int radius = 1; RoundGlyph(int r){ radius = r ; System.out.println("RoundGlyph.RoundGlyph(),radius="+radius); } void draw(){ System.out.println("RoundGlyph.draw(), radius="+radius); } }
public class PolyConstructors { public static void main(String[] args){ new RoundGlyph(5); } }
Glyph() before draw() RoundGlyph.draw(), radius=0 Glyph() after draw() RoundGlyph.RoundGlyph(),radius=5
1、在其他任何事物发生之前,将分配给对象的存储空间初始化成二进制的零。
2、如前所述那样调用基类构造器,此时,调用被覆盖后的draw()方法,(要在调用RoundGlyph构造器之前调用),由于步骤1的原因,radius的值为0
3、按照声明的顺序调用成员的初始化方法。
4、调用导出类的构造器主体。
因此,编写构造器时有一条有效的准则,用尽可能简单的方法使对象进入正常状态,如果可以的话,避免调用其他方法。