我已经看到一些资源,它声明动态调度和后期绑定是相同的。如果是,那么binding
应该等于dispatching
。在某些地方,他们将overloading/early binding/ static dispatch
视为相同,overriding/late binding/ dynamic dispatch
同样相同。
所以我想出了一个类比来理解这一点。 以下类比是否正确? 或如何修改以下说明。
我们有一个类结构如下。
class Board {
public void show(){};
}
class Shape{
public void draw(Board board) {};
}
class Square extends Shape {
public void draw(Board board) {
System.out.println("Drawing a Square");
};
}
class Circle extends Shape {
public void draw(Board board) {
System.out.println("Drawing a Circle");
};
}
我们有:
Shape shape = createShape(type); // This will return any of Shape, Square, Circle
shape.draw(board);
我们有:
Board myBoard = new Board();
myBoard.show();
我想出了一些解释,
绑定:确定
shape
的实际类型(可以是Shape,Square或Circle)。假设只有shape
的类型在运行时才知道它是late binding
。确定myBoard
的类型可以在编译时完成。这是early binding
调度:确定
draw
的实际实施被视为dispatching
。鉴于如果draw
的实际实现只能在运行时决定它是dynamic dispatching
,否则如果可以在编译时决定它被称为static dispatching
静态调度:当我在编译时知道在调用方法时将执行哪个函数体时发生。所以
myBoard.show()
,这里可以静态调度方法show
。shape.draw(board)
我们无法静态发送draw
,因为我们无法保证在运行时将执行哪个函数体。单一调度(动态):仅根据
draw
类型选择shape
的实施,忽略{的类型或值{1}}。多个调度(动态):
board
和shape
的类型共同决定了将执行哪个board
操作。 (在这种情况下,它是draw
)
我使用的资源很少:
答案 0 :(得分:1)
最后给这个问题一个答案:
绑定和 dispatch 不同。
Binding 通常是指将符号解析为某个值/对象/实现。例如,赋值语句x = 42
将符号x
绑定到表达式42
的值。类型名称始终可以在Java编译期间进行解析。
Dispatch (或更准确地说是 call dispatch 或 method dispatch )是解决方法调用(或函数调用)的方法实现。使用静态调度或早期绑定,可以在编译时通过动态调度或 late绑定知道该调用的目标方法调用的em>在运行时被选择。
接口方法或虚拟方法(Java中的默认方法)使用动态调度。有效地静态分配了final方法,私有方法和静态方法(尽管严格来说,JVM仍然必须解决该调用)。
我还将很快提到表达式的静态类型是表达式的静态已知或“声明的”类型,而动态类型 是表达式的该表达式的运行时值的实际类型。例如。当我们声明变量Board b
时,b
的静态类型是Board
类,但动态类型可能是Board
或其任何子类–我们没有知道,直到它被分配一个特定的对象。一旦知道动态类型,就可以绑定动态调度的方法(假设像Java中那样基于类型的单一调度)。
您的myBoard.show()
示例使用虚拟方法,通常会动态调度:myBoard
被声明为类型Board
或任何Board
子类。如果您将类或show()
声明为final,则情况会有所改变。实际上,可以在静态范围内优化此特定示例,因为您在同一范围内构造了new Board()
,所以myBoard
的动态类型是已知的。但这只是一种优化。
相反,您的createShape().draw()
示例显然是动态调度,因为调用者不知道createShape()
的动态类型。
您对单次/多次调度的理解基本上是正确的。
我想指出的是,在解决函数调用的一般意义上,“分派”不一定限于类型。我们还可以在if / elses中使用逻辑调度呼叫。考虑以下示例,在该示例中,我们根据x和y的值向特定象限(如东北)调度quadrant(x,y)
调用。从语言的角度来看,这是静态调度,但从程序员的角度来看,其行为更像是静态调度。
class Quadrants {
...
public static void quadrant(int x, int y, String value) {
// dispatch a call with a x→east, y→north coordinate system
if (x >= 0) {
if (y >= 0) {
quadrantNE(value);
} else {
quadrantSE(value);
}
} else {
if (y >= 0) {
quadrantNW(value);
} else {
quadrantSW(value);
}
}
}
private static void quadrantNE(String value) { ... }
private static void quadrantNW(String value) { ... }
private static void quadrantSE(String value) { ... }
private static void quadrantSW(String value) { ... }
}
在后台,语言运行库也将仅使用某些逻辑来执行动态调度,尤其是对于多调度。基于类型的单调度(如Java中静态类型为类的实例方法调用)可以通过简单的表查找(vtable调度)来实现,并且不需要复杂的逻辑。