Common Lisp 对象系统中的泛型调度与经典 OOP 中的动态调度是否相同?

Is generic dispatch in Common Lisp Object System the same as Dynamic Dispatch in classic OOP?

我正在阅读 Sonja Keene 的书 Common Lisp 中的面向对象编程

在第二章中,作者说:

The procedure for determining which methods to call and then calling them is called generic dispatch. It happens automatically whenever a generic function is called.

这让我想起了动态调度定义(根据 Wikipedia):

Dynamic dispatch is the process of selecting which implementation of a polymorphic operation to call at run time. It is commonly employed in, and considered a prime characteristic of, object-oriented programming languages and systems.

不幸的是,维基百科 没有 有关于 generic dispatch 的条目。

因此,我想问一下:

1 - 动态调度和通用调度基本上是一回事吗?有什么相似之处?

2 - 有什么区别?由于 CLOS 的灵活性,动态调度是否是通用调度的某种子集?

是的,CLOS中的dispatch也是dynamic(这也叫late binding

不,动态调度和通用调度不是一回事,因为 genericdynamic 回答不同的问题。

dynamic 这个词的意思是,在 运行 时决定调用哪个方法。与之相反的是 static dispatch(有些人不会称其为 dispatch,而是 overloading),其中该决定是在编译时做出的。

generic 这个词的意思是,根据所有(必需的)参数的类型决定调用哪个或哪些方法。这些方法附加到 通用函数 。与之相反的是基于 class 的 分派,其中仅根据第一个参数的 class 做出决定,并且方法附加到 class.

通常 generic dispatch 只是意味着 selecting 一个 generic function 的实现基于一个或多个参数.

这适用于单分派(如 Lisp 的 Flavors 系统)或多分派(就像 Lisp 的 CLOS)。

在 CLOS 和 Flavors 中,通用函数 捆绑了各种方法。这些方法可能是不同的方法类型(主要、之前、之后……)and/or 专门用于一种或多种参数类型。

Flavors 和 CLOS 的通用调度选择适用方法并计算有效方法,然后使用提供的方法调用该方法参数。

示例:

CL-USER 7 > (defmethod greet :before ((w world)) (princ "hello"))  
#<STANDARD-METHOD GREET (:BEFORE) (WORLD) 40200211B3>

CL-USER 8 > (defmethod greet ((w world)) (princ "world") (values)) 
#<STANDARD-METHOD GREET NIL (WORLD) 40200221F3>

CL-USER 9 > (defmethod greet :after ((w world)) (princ "."))  
#<STANDARD-METHOD GREET (:AFTER) (WORLD) 402002317B>

CL-USER 10 > (greet (make-instance 'world))
helloworld.

如您所见,通用调度机制会自动按指定顺序调用多个不同的适用方法。

CLOS 的通用调度也可以 select 基于所有必需参数及其类型的方法 -> 多重调度。

总结:CLOS(和 Flavors,...)中的通用调度意味着 selecting 适用方法 AND 组合他们是一种有效的方法。这是动态调度的一种特殊形式。动态调度 OTOH 通常只是调用一种方法,并且通常只 selected 基于一个参数。然后,CLOS 以多种调度和方法组合的形式支持通用调度。