Java编程思想读书笔记--第八章 多态

多态概述

在面向对象的程序设计语言中,多态是继数据抽象和继承之后的第三种基本特征

  • 多态不但能够改善代码的组织结构可读性,还能够创建可扩展的程序。
  • 在多态允许我们无需管导出类(子类)的存在,编写的代码只是与基类(父类)打交道
  • 多态别称:又叫动态绑定后期绑定运行时绑定

    • 绑定:将一个方法调用与一个方法主体关联起来称作绑定

    • 前期绑定:若在程序执行前进行绑定(如果有的话,由编译器和连接程序实现),叫做前期绑定。它是面向过程语言中不需要选择就默认的绑定方式。例如,C只有一种方法调用,那就是前期绑定。

    • 后期绑定:就是在运行时根据对象的类型进行绑定。后期绑定也叫做动态绑定或运行时绑定。如果一种语言想实现后期绑定,就必须具有某种机制,以便在运行时能判断对象的类型,从而调用恰当的方法。也就是说,编译器一直不知道对象的类型,但是方法调用机制能找到正确的方法体,并加以调用。后期绑定机制随编程语言的不同而有所不同,但是只要想一下就会得知,不管怎样都必须在对象中安置某种“类型信息”。

      再论final

  • 可以防止其他人覆盖该方法
  • 还可以有效的”关闭”动态绑定
  • private(隐形final)不可被覆盖

论static

  • 如果某个方法是静态的,它的行为就不具有多态性
  • 静态方法是与类,而非与单个的对象相关联的。
  • static不可以被重写,但可以被重载

构造器

  • 构造器(隐式static),同样不具有多态性
  • 构造器特殊任务:检查对象是否被正确的构造

对象调用构造器遵从顺序:

  • 调用基类构造器,这个步骤或不断的反复递归下去,首先是构造这种层次结构的根,然后是下一层导出类,直到最底层的导出来
  • 按照声明顺序调用成员的初始化方法
  • 调用导出类构造器的主体

构造器内部的多态方法的行为

如果在一个构造器的内部调用正在构造的对象的某个动态绑定方法,那么会发生什么情况呢?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
/**
* 构造器内部的多态方法的行为
*/
public class PolyConstructors {
public static void main(String[] args) {
new RoundGlyph(5);
}
}

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

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

class RoundGlyph extends Glyph{
private int radius = 1;

public RoundGlyph(int radius) {
this.radius = radius;
System.out.println("RoundGlyph.RoundGlyph(),radius="+radius);
}
void draw(){
System.out.println("RoundGlyph.draw(),radius="+radius);
}
}/*Output:
Glyph() before draw()
RoundGlyph.draw(),radius=0
Glyph() after draw()
RoundGlyph.RoundGlyph(),radius=5
*///:~

由上可以看出,在打印radius时,不是我们默认初始化的1,而是0。违背了我们的初衷。我们要用尽可能简单的方法使对象进入正常状态;如果可以的话,避免调用其他方法。

初始化的实际过程是:
- 在其他任何事物发生之前,将分配给对象的存储空间初始化成二进制的零
- 如前所述的那样调用及剋构造器。
- 按照声明的顺序调用成员的初始化方法
- 调用导出类的构造主体