谈论“多态”需要首先涉及“前期绑定”和“后期绑定”。
一、前期绑定
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();
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();
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();
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) { 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();
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();
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();
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();
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();
System.out.println(polymorphic8.f());
A13 a13 = new A13(); System.out.println(a13.f()); }
private int f() { return 40; } }
class A13 extends Polymorphic8 {
int f() { return 30; } }
|
综上,多态的本质为:访问“一般方法”成员,后期绑定可以改变前期绑定的结果。