多态可以是客户端使用统一的接口执行不同的行为。统一的接口是因为继承类都覆盖了基类方法,从而为自己定义了单独的行为。“向上转型”(upcasting,将继承类对象赋给基类对象的一种行为)和动态编译能够确定执行哪段代码。如下:

class Shape{
 void draw(){
  System.out.println("Shape.draw()");
 }
}

class Circle extends Shape{
 void draw(){
  System.out.println("Circle.draw()");
 }
}

public class PolyTest{
 public static void f(Shape s){
 s.draw();
}

 public static void main(String[] args){
  Circle c=new Circle();
  f(c);
 }
}

运行结果:
Circle.draw()

从上面的代码可以看到,无论载main函数里面生成什么对象Circle、triangle等,只要交给void f(Shape s)函数去办就可以了,它知道应该调用哪一段代码,即产生正确的行为,多代使得我们代码量减少而且容易扩展。

如果在构造器调用多态的函数,那么就容易产生一些问题,如下所示:

class Glyph{
 void draw(){System.out.println("Glyph.draw()");};
 Glyph(){
  System.out.println("Glyph() before draw()");
  draw();
  System.out.println("Glyph() after draw()");
 }
 
}

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

因为 new RoundGlyph(5)会先调用基类的构造器,所以第一句结果没问题,而基类的构造起调用了draw()方法,这个时候产生了多态,即实际调用继承类的draw()方法,但是为什么打印的是radius=0呢?为什么不是radius=5或编译通不过,radius没有定义?编译确实没有出问题,原来初始化最开始一步并不是调用基类的构造函数,而是将分配给对象的存储空间初始化为零,也就是说radius在调用基类构造函数之前就已经初始化了,只是初始化值为0。所以输出结果为radius=0。这个输出结果并不是我们所希望的,所以编写构造起时记住一个原则:尽可能简单使对象进入正常状态,如果可以的话,避免调用其他方法。当然调用基类的final方法和private方法是安全的。