<!-- @page { margin: 0.79in } P { margin-bottom: 0.08in } -->
对 java中的多态的理解
Thinking in java中的一个例子:
构造器中的多态:
public class Glyph { int radius = 5; void draw() { System.out.println("Glyph.draw()"); System.out.println(this.getClass()); } static void showInfo() { System.out.println("Glyph showInfo"); } Glyph() { System.out.println("Glyph() before draw()\n\tradius="+radius); draw(); showInfo(); System.out.println("Glyph() after draw()"); } }
class RoundGlyph extends Glyph { private int radius = 10; RoundGlyph(int r) { System.out.println("RoundGlyph.radius="+radius); radius = r; System.out.println("RoundGlyph.RoundGlyph()\n\tthis.radius=" + this.radius+"\tsuper.radius="+super.radius); } void draw() { System.out.println("RoundGlyph.draw(), radius = " + radius); System.out.println(this.getClass()); System.out.println(super.getClass()); } static void showInfo() { System.out.println("RoundGlyph showInfo"); } }
public class PolyConstructors { public static void main(String[] args) { new RoundGlyph(15); System.out.print("\n\n\n"); new Glyph(); } }
运行输出:
Glyph() before draw()
radius=5
RoundGlyph.draw(), radius = 0
class RoundGlyph
class RoundGlyph
Glyph showInfo
Glyph() after draw()
RoundGlyph.radius=10
RoundGlyph.RoundGlyph()
this.radius=15 super.radius=5
Glyph() before draw()
radius=5
Glyph.draw()
class Glyph
Glyph() after draw()
对输出结果的解释:
复杂对象调用构造器要遵照下面的顺序 :
1. 调用基类构造器。这个步骤会不断地反复递归下去 , 首先是构造这种层次结构的根 ,
然后是下一层导出类 , 等等。直到最低层的导出类。
2. 按声明顺序调用成员的初始状态设置模块。
3. 调用导出类构造器的主体。
初始化的实际过程是 :
1. 在其他任何事物发生之前 , 将分配给对象的存储空间初始化成二进制的零。
2. 如前所述的那样 , 调用基类构造器。此时 , 调用被重载的 draw() 方法 ( 是的 , 是
在调用 RoundGlyph 构造器之前调用的 ), 由于步骤 (1) 的缘故 , 我们此时会发
现 radius 的值为 0 。
3. 按照声明的顺序调用成员的初始化代码。
4. 调用导出类的构造器主体。
在本例中为:
分配内存并初始化为二进制的零。调用 Glyph 中的成员初始状态设置模块即 radius=5; 接着调用 Glyph 类的构造器 Glyph():
System.out .println("Glyph() before draw()\n\tradius=" +radius );
输出:
Glyph() before draw()
radius=5
draw();
输出:
RoundGlyph.draw(), radius = 0 // ( 此处为什么是 0, 而不是 5)
class RoundGlyph
class RoundGlyph
showInfo();
输出:
Glyph showInfo
System. out .println( "Glyph() after draw()" );
输出:
Glyph() after draw()
这后调用 RoundGlyph 中的成员初始状态设置模块即 radius=10;( 由于在基类及导出类类都定义了 radius ,因此当在 RoundGlyph 类中定义的 radius 会覆盖在 Glyph 中定义的 radius, 两个 radius 都存在但不同。然后就是调用导出类中的构造器 RoundGlyph():
输出:
RoundGlyph.RoundGlyph()
this.radius=15 super.radius=5
java 中方法的动态绑定:
非静态方法调用时有一个隐式的参数 this, 表示当前对象。本例中的 Glyph 中的 draw(), 实际上为 draw(Glyph this), RoundGlyph 中的 draw() 为 draw(RoundGlyph this). 静态方法是在编译时绑定的,非表态方法是运行时动态绑定的。由于每个非静态方法都有一个 this 参数, 虚拟机由此可以确定是函数是属于哪一个类的,并该类的函数表中去查找此函数, 如果能找到该函数,否则到基类的函数表是去查找,依此类推。