什么是动态方法调度以及它与继承的关系?

Sub*_*hra 5 java

Java中的动态分派是什么意思,为什么我们在继承的上下文中需要它?

aio*_*obe 12

Java [...]中的动态调度是什么意思?

将"调度"视为"确定调用哪种方法".

"动态"部分简单地说它是在运行时确定的.也就是说,在运行时确定要调用的方法.

为什么我们在继承的背景下需要它

没有继承/多态,我们就不需要这个.表达式的类型在编译时是可判定的,并且在编译程序时将知道在运行时调用的方法.

对于继承/多态,我们不知道表达式的具体运行时类型,因此必须在运行时"动态"确定要调用的方法.

如果没有动态调度,虚拟方法就没有意义,这对于抽象和封装至关重要.

推荐阅读:关于动态调度的维基百科文章

  • 这很简单:如果你不被允许执行 `List<String> l = new ArrayList<>();` 但_had_ 执行 `ArrayList<String> l = new ArrayList<>();` 你就不会需要动态调度,因为运行时“l”的类型必然是“ArrayList”(即它不能是任何其他“List”)。这将使动态分派变得毫无意义,因为编译器可以将“l.add(...)”的调用硬连接到“ArrayList.add”方法(而不是将其连接到“List.add”并将其分派到动态地`ArrayList.add`或`LinkedList.add`)。 (2认同)

Ral*_*lph 11

其他答案讨论了这个理论,这是一个例子,说明为什么需要动态调度(也称为后期绑定).

假设你有一个Class'Rectangle`.

public class Rectangle{
  public void draw() {
     System.out.println("___\n| |\n---");
     //does it look nice?
  }
}
Run Code Online (Sandbox Code Playgroud)

你有一个圆角的子类

public class RoundedRectangle extends Rectangle {
  @Override
  public void draw() {
     System.out.println("assume it is a rectangle with rounded corners");
  }
}
Run Code Online (Sandbox Code Playgroud)

现在假设你有一个方法得到一个类型为Rectangle的参数,该方法用于调用draw方法

public class Demo() {
...
  public demonstration(Rectangle rect) {
    rect.draw();
  }
...
}
Run Code Online (Sandbox Code Playgroud)

这个方法的参数是Rectangle类然后它将绘制

___
| |
---
Run Code Online (Sandbox Code Playgroud)

但是当参数是RoundedRectangle类型时,我们期望:

assume it is a rectangle with rounded corners
Run Code Online (Sandbox Code Playgroud)

这就是需要后期绑定的地方:当代码编译时,不清楚rect.draw()需要调用哪个方法; 我可以是Rectangle.draw(),RoundedRectangle.draw(),或任何其他尚未实现的Rectangle子类的draw方法.

摘要(从开发人员的角度来看):

所以后期绑定意味着:为一个只知道它是特定类或子类的实例调用给定签名的方法(方法名称和参数列表) - 但不知道它究竟是哪个类.当一个方法被覆盖时,然后调用覆盖方法.

所以没有多态性与晚期绑定 - 当你有多态性时,你需要晚期绑定.在Java和C++中(我相信,在其他所有面向对象的语言中)