0%

多态

谈论“多态”需要首先涉及“前期绑定”和“后期绑定”。

一、前期绑定

1.1、概念

在编译期,完成前期绑定。

1.1.1、“实例对象访问成员”形式的前期绑定

实例对象访问成员,参见如下示例代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
package chapter8;

public class A {

static int b = 20;

int a = 10;

static int g() {
return 40;
}

int f() {
return 30;
}

public static void main(String[] args) {
A a = new A();
System.out.println(a.a);
System.out.println(a.b);
System.out.println(a.f());
System.out.println(a.g());
}
}

前期绑定描述:

  • 确定实例对象对应的声明Java类(注意不是实例对象对应的实际Java类),基于该声明Java类的实际定义进行访问成员的绑定
  • 当该声明Java类的实际定义中含有0个匹配的候选项时,前期绑定失败,编译报错;当该声明Java类的实际定义中含有大于0个匹配的候选项时,依据一定的策略进行选取绑定(笔者不在这里探讨详细的策略),比如“原生成员优先级高于继承成员”,如果由于“违反约束条件”等原因导致不能顺利选取绑定则前期绑定失败,编译报错,否则前期绑定成功

1.1.2、“直接通过类访问成员”形式的前期绑定

直接通过类访问成员,参见如下示例代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
package chapter8;

public class A {

static int b = 20;

int a = 10;

static int g() {
return 40;
}

int f() {
return 30;
}

public static void main(String[] args) {
System.out.println(A.b);
System.out.println(A.g());
}
}

前期绑定描述:

  • 基于所使用Java类的实际定义进行访问成员的绑定
  • 当该使用Java类的实际定义中含有0个匹配的候选项时,前期绑定失败,编译报错;当该使用Java类的实际定义中含有大于0个匹配的候选项时,依据一定的策略进行选取绑定(笔者不在这里探讨详细的策略),比如“原生成员优先级高于继承成员”,如果由于“违反约束条件”等原因导致不能顺利选取绑定则前期绑定失败,编译报错,否则前期绑定成功

1.2、几个例子

1.2.1、例子1

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
package chapter8;

public class Polymorphic1 extends A1 {

int a = 20;

public static void main(String[] args) {
A1 a1 = new Polymorphic1();

//结果为10
System.out.println(a1.a);
}
}

class A1 {

int a = 10;
}

1.2.2、例子2

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
package chapter8;

public class Polymorphic2 extends A3 {

public static void main(String[] args) {
Polymorphic2 polymorphic2 = new Polymorphic2();

//结果为30
System.out.println(polymorphic2.a);
}
}

class A2 {

int a = 10;
}


class A3 extends A2 {

int a = 30;
}

1.2.3、例子3

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
package chapter8;

interface A5 {

int a = 40;
}

public class Polymorphic3 extends A4 implements A5 {

public static void main(String[] args) {
Polymorphic3 polymorphic3 = new Polymorphic3();

//提示: Reference to 'a' is ambiguous, both 'A4.a' and 'A5.a' match
System.out.println(polymorphic3.a);
}
}

class A4 {

int a = 10;
}

1.2.4、例子4

1
2
3
4
5
6
7
8
9
10
11
12
13
14
package chapter8;

public class Polymorphic9 extends A15 {

public static void main(String[] args) {
//结果为10
System.out.println(Polymorphic9.a);
}
}

class A15 {

static int a = 10;
}

二、后期绑定

2.1、概念

在运行期,完成后期绑定。
后期绑定只针对“一般方法”成员,因此只有“实例对象访问成员”形式的后期绑定。
后期绑定描述:

  • 需要特别注意的是,在后期绑定之前已经完成了前期绑定,如果后期绑定未作重新绑定,则使用前期绑定的结果
  • 确定实例对象对应的实际Java类,基于该实际Java类的实际定义查找覆盖欲访问一般方法的方法
  • 当该实际Java类的实际定义中含有0个匹配的候选项时,后期绑定未作重新绑定,使用前期绑定的结果,运行不报错;当该实际Java类的实际定义中含有大于0个匹配的候选项时,依据一定的策略进行选取绑定(笔者不在这里探讨详细的策略),比如“必须是非虚方法”,“原生一般方法优先级高于继承一般方法”等,如果由于“违反约束条件”等原因导致不能顺利选取绑定则后期绑定失败,运行报错,否则后期绑定成功,后期绑定作重新绑定

2.2、几个例子

2.2.1、例子1

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
package chapter8;

public class Polymorphic4 extends A6 {

public static void main(String[] args) {
Polymorphic4 polymorphic4 = new Polymorphic4();

//结果为20
System.out.println(polymorphic4.f());
}

int f() {
return 20;
}
}

abstract class A6 {

abstract int f();
}

2.2.2、例子2

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
package chapter8;

public class Polymorphic5 extends A8 {

public static void main(String[] args) {
A7 a7 = new Polymorphic5();

//结果为30
System.out.println(a7.f());
}

int f() {
return 30;
}
}

class A7 {

int f() {
return 10;
}
}

class A8 extends A7 {

int f() {
return 20;
}
}

2.2.3、例子3

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
package chapter8;

interface A9 {

int f();
}

public class Polymorphic6 extends A10 {

public static void main(String[] args) {
Polymorphic6 polymorphic6 = new Polymorphic6();

//结果为30
System.out.println(polymorphic6.f());
}
}

class A10 implements A9 {

public int f() {
return 30;
}
}

2.2.4、例子4

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
package chapter8;

interface A12 {

int f();
}

public class Polymorphic7 extends A11 implements A12 {

public static void main(String[] args) {
Polymorphic7 polymorphic7 = new Polymorphic7();

//结果为30
System.out.println(polymorphic7.f());
}
}

class A11 {

public int f() {
return 30;
}
}

2.2.5、例子5

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
package chapter8;

public class Polymorphic8 {

public static void main(String[] args) {
Polymorphic8 polymorphic8 = new A13();

//结果为40
System.out.println(polymorphic8.f());

//结果为30
A13 a13 = new A13();
System.out.println(a13.f());
}

private int f() {
return 40;
}
}

class A13 extends Polymorphic8 {

/**
* 未继承覆盖Polymorphic8中的“int f()”方法,因此关于该一般方法无后期绑定
*/
int f() {
return 30;
}
}

综上,多态的本质为:访问“一般方法”成员,后期绑定可以改变前期绑定的结果。
您的支持将鼓励我继续分享!