Java 绑定和分派的关系是什么?它们是一样的吗?
我在一些参考资料中看到,动态分派和后期绑定是相同的。如果是这样的话,Java 绑定和分派的关系是什么?它们是一样的吗?,java,oop,Java,Oop,我在一些参考资料中看到,动态分派和后期绑定是相同的。如果是这样的话,绑定应该等于调度。在某些地方,它们将重载/早期绑定/静态调度声明为相同,将覆盖/后期绑定/动态调度声明为相同 所以我想出了一个类比来理解这一点下面的类比正确吗?或者我如何修改下面的解释 我们的班级结构如下 class Board { public void show(){}; } class Shape{ public void draw(Board board) {}; } class Square ext
绑定
应该等于调度
。在某些地方,它们将重载/早期绑定/静态调度
声明为相同,将覆盖/后期绑定/动态调度
声明为相同
所以我想出了一个类比来理解这一点下面的类比正确吗?或者我如何修改下面的解释
我们的班级结构如下
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 = createShape(type); // This will return any of Shape, Square, Circle
shape.draw(board);
Board myBoard = new Board();
myBoard.show();
我想不出什么解释
绑定:确定形状
的实际类型(可以是形状、正方形或圆形)。假设只有在运行时才知道形状
的类型,那么它就是后期绑定
。可以在编译时决定myBoard
的类型。这是早期绑定
调度:决定绘图
的实际实施被视为调度
。假设draw
的实际实现只能在运行时决定,则为动态调度
,否则,如果可以在编译时决定,则称为静态调度
静态分派:当我在编译时知道调用方法时将执行哪个函数体时发生。因此myBoard.show()
,这里可以静态调度方法show
。其中shape.draw(board)
我们不能静态地分派draw
,因为我们不能保证在运行时执行哪个函数体
单一分派(动态):将仅根据形状
的类型选择绘图
的实现,而不考虑板
的类型或值
多重分派(动态):将执行的绘图操作由形状
和板
的类型共同决定。(在这种情况下,它是双重分派
)
我使用的资源很少:
- 绑定通常指将符号解析为某个值/对象/实现。例如,赋值语句
将符号x=42
绑定到表达式x
的值。在Java中,类型名始终可以在编译时解析42
- 分派(或者更准确地说是调用分派或方法分派)是将方法调用(或函数调用)解析为方法实现的一种绑定。对于静态分派或早期绑定,可以在编译时知道该调用的目标;对于方法调用的动态分派或后期绑定,可以在运行时选择目标 接口方法或虚拟方法(Java中的默认方法)使用动态分派。最终方法、私有方法和静态方法是有效的静态调度(尽管严格来说,JVM仍然必须解析调用)
Board b
时,b
的静态类型是Board
类,但动态类型可能是Board
或其任何子类–在为其分配特定对象之前,我们不知道。动态分派的方法可以在动态类型已知后立即绑定(假设在Java中是基于类型的单一分派)
您的myBoard.show()
示例使用虚拟方法,通常会动态调度:myBoard
声明为具有typeBoard
或任何Board
-子类。如果您将类或show()
声明为final,则会发生更改。实际上,此特定示例可以优化为静态调度,因为您在同一范围内构造了newboard()
,因此myBoard
的动态类型是已知的。但这只是一种优化
相反,您的createShape().draw()
示例显然是动态分派,因为调用方不知道createShape()
的动态类型
您对单次派送/多次派送的理解基本正确
我想指出,“分派”在解析函数调用的一般意义上并不一定局限于类型。我们还可以使用if/elses中的逻辑来调度调用。考虑这个例子,根据x和y的值,我们将一个<代码>象限(x,y)< /COD>调用到一个类似于东北的特定象限。从语言的角度来看,这是静态分派,但从程序员的角度来看,其行为更像静态分派
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 dispatch)实现,并且不需要复杂的逻辑。“如果是这样的话,
绑定
应该等于分派
”——我不会这么说。“绑定”是指将标识符与方法相关联。“调度”是指进行实际呼叫。但是,如果您“绑定得晚”,那么就没有必要分派到静态决定的方法。如果您“提前绑定”,您没有选择余地,您必须在编译时选择一个方法。那么,延迟绑定实际上是动态调度吗?关于上述解释,你能说些什么