Common Lisp 对象系统中的通用调度与经典 OOP 中的动态调度相同吗?

Ped*_*ino 3 oop common-lisp dynamic-dispatch clos

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

在第 2 章中,作者说:

确定调用哪些方法然后调用它们的过程称为泛型调度。每当调用通用函数时,它都会自动发生。

这让我想起了 Dynamic Dispatch 定义(根据Wikipedia):

动态分派是选择在运行时调用多态操作的哪个实现的过程。它通常用于面向对象的编程语言和系统,并被认为是面向对象的编程语言和系统的主要特征。

不幸的是,维基百科目前具备有关条目的通用调度。

因此,我想问:

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

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

Rai*_*wig 6

通常泛型调度只是意味着选择基于一个或多个参数的泛型函数的实现。

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

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

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.
Run Code Online (Sandbox Code Playgroud)

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

CLOS 的泛型分派还可以根据所有必需的参数及其类型选择方法 -> 多分派。

摘要:在CLOS通用调度(和香料,...)来选择适用的方法将它们组合到一个有效的方法。这是动态调度的一种特殊形式。动态调度 OTOH 通常只调用一种方法,并且通常只根据一个参数进行选择。然后 CLOS 以多种分派和方法组合的形式支持通用分派。


Sva*_*nte 5

是的,CLOS 中的调度也是动态的(这也称为后期绑定)。

不,动态和通用调度不是同一件事,因为通用动态这两个词回答了不同的问题。

动态这个词的意思是,调用哪个方法的决定是在运行时做出的。与此相反的是静态调度(有些人不会称为调度而是重载),其中决定是在编译时做出的。

泛型这个词的要点是,调用哪个方法的决定是根据所有(必需的)参数的类型做出的。这些方法附加到通用函数上。与此相反的是基于类的调度,其中仅根据第一个参数的类做出决定,并且方法附加到该类。