0%

多态

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

一、前期绑定

1.1、概念

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

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

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

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、“直接通过类访问成员”形式的前期绑定

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

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

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

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

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

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

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

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

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

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

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;
  }
}

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