fbpx
维基百科

多分派

多分派或译多重派发(multiple dispatch)或多方法(multimethod),是某些编程语言的一个特性,其中的函数或者方法,可以在运行时间(动态的)基于它的实际参数的类型,或在更一般的情况下于此之外的其他特性,来动态分派[1]。这是对单分派多态的推广, 那里的函数或方法调用,基于在其上调用方法的对象的派生类型,而动态分派。多分派使用一个或多个实际参数的组合特征,路由动态分派至实现函数或方法。

理解分派

软件工程师通常把代码写进代码块中,代码块通常称作过程、函数、方法。代码通过被调用来执行,调用时将控制权传入函数中,当函数执行完成后将控制权返回给调用者。

函数名通常用来描述函数的目的。有时会将多个函数起同样的名称。比如同名函数在逻辑上处理相同的任务,但是操作在不同类型的输入值上。在这种情况下,无法仅仅通过函数名,来判断目标代码块。那么,函数的实际参数的个数和类型,也就被用来判断。

通常,单分派面向对象语言,在调用一个方法时,方法参数中一个参数会被特殊对待,并用来决定哪一个方法(如果有多个同名方法)会被调用。在许多语言中,这个特殊的参数是在语法上指明的,许多编程语言在调用方法时,把特殊参数放在小圆点(.)之前。例如 special.method(other, arguments, here),这样 lion.sound() 将会发出狮吼,同时 sparrow.sound() 只会吱吱地叫。一般来说,对于面向对象的编程语言,这个小圆点之前的参数(上例中的lionsparrow)被称为接收者[2]

相反,在实现了多分派的语言中,被调用的函数,即是那些参数个数一样多,并且类型也匹配的调用。在调用中并没有特殊参数,来决定那个方法被调用。也就是说,所有参数的运行时类型都参与分派。CLOS是早期和著名的多分派语言。

数据类型

对于编译时间可以区分数据类型的编程语言,在交替英语Alternation (formal language theory)(alternative)函数中进行选择,可以发生在编译时间,创建交替函数用于编译时间选择的活动,通常被叫做函数重载

在有些编程语言中,这种数据类型的识别,可以被延后至运行时间(后期绑定英语Late binding)。交替函数的选择发生在运行时间,并依据动态确定的函数实际参数的类型。以这种方式选择交替实现的函数,通常被称为多方法。

例子

可以通过例子更加清晰的区分多分派和单一分派。假想一个游戏,它有两种(用户可见的)物体:飞船和小行星。当两个物体要相撞的时候,程序需要依据什么物体要相撞而做不同的事情。

具有内建多分派的语言

Common Lisp

在具有多分派的Common Lisp语言中,可以在Common Lisp对象系统中如下这样实现:

(defgeneric collide (x y)) (defclass asteroid () ()) (defclass spaceship () ()) (defmethod collide-with ((x asteroid) (y asteroid)) ;; deal with asteroid hitting asteroid ) (defmethod collide-with ((x asteroid) (y spaceship)) ;; deal with asteroid hitting spaceship ) (defmethod collide-with ((x spaceship) (y asteroid)) ;; deal with spaceship hitting asteroid ) (defmethod collide-with ((x spaceship) (y spaceship)) ;; deal with spaceship hitting spaceship ) 

并且对其他方法也是类似的。没有使用显式测试和“动态转换”。

由于多分派的存在,方法要定义在类中并包含在对象中的传统想法,变得不再吸引人了,上述每个collide-with方法,都附属于两个不同的类而非一个类。因此方法调用的特殊语法,一般会消失,从而方法调用看起来完全就像正常的函数调用,并且方法被组织入泛化函数而非类中。

Julia

Julia有内建的多分派,并且它是语言设计的中心[3]。Julia版本的例子如下:

collide_with(x::Asteroid, y::Asteroid) = ... # deal with asteroid hitting asteroid collide_with(x::Asteroid, y::Spaceship) = ... # deal with asteroid hitting spaceship collide_with(x::Spaceship, y::Asteroid) = ... # deal with spaceship hitting asteroid collide_with(x::Spaceship, y::Spaceship) = ... # deal with spaceship hitting spaceship 

C#

C#在版本4(2010年4月),使用关键字dynamic,介入了对动态多方法的支持[4]。下面的例子展示多方法协同于在版本8(2019年9月)中介入的switch表达式[5]。像很多其他静态类型的语言语言一样,C#还支持静态方法重载[6],Microsoft预期开发者在多数场景下会选用静态类型超过动态类型[7]dynamic关键字支持COM对象和动态类型的.NET语言的互操作。

class Program {  static void Main()  {  Console.WriteLine(Collider.Collide(new Asteroid(101), new Spaceship(300)));  Console.WriteLine(Collider.Collide(new Asteroid(10), new Spaceship(10)));  Console.WriteLine(Collider.Collide(new Spaceship(101), new Spaceship(10)));  } } static class Collider {  public static string Collide(SpaceObject x, SpaceObject y) =>  ((x.Size > 100) && (y.Size > 100)) ?  "Big boom!" : CollideWith(x as dynamic, y as dynamic);  private static string CollideWith(Asteroid x, Asteroid y) => "a/a";  private static string CollideWith(Asteroid x, Spaceship y) => "a/s";  private static string CollideWith(Spaceship x, Asteroid y) => "s/a";  private static string CollideWith(Spaceship x, Spaceship y) => "s/s"; } abstract class SpaceObject {  public SpaceObject(int size) => Size = size;  public int Size { get; } } class Asteroid : SpaceObject {  public Asteroid(int size) : base(size) { } } class Spaceship : SpaceObject {  public Spaceship(int size) : base(size) { } } 

输出:

big-boom a/s s/s 

Groovy

Groovy是通用的Java兼容/互用的JVM语言,它对立于Java,使用后期绑定/多分派[8]

/*  Groovy implementation of C# example above  Late binding works the same when using non-static methods or compiling class/methods statically  (@CompileStatic annotation) */ class Program { static void main(String[] args) { println Collider.collide(new Asteroid(101), new Spaceship(300)) println Collider.collide(new Asteroid(10), new Spaceship(10)) println Collider.collide(new Spaceship(101), new Spaceship(10)) } } class Collider { static String collide(SpaceObject x, SpaceObject y) { (x.size > 100 && y.size > 100) ? "big-boom" : collideWith(x, y) // Dynamic dispatch to collideWith method } private static String collideWith(Asteroid x, Asteroid y) { "a/a" } private static String collideWith(Asteroid x, Spaceship y) { "a/s" } private static String collideWith(Spaceship x, Asteroid y) { "s/a" } private static String collideWith(Spaceship x, Spaceship y) { "s/s"} } class SpaceObject { int size SpaceObject(int size) { this.size = size } } @InheritConstructors class Asteroid extends SpaceObject {} @InheritConstructors class Spaceship extends SpaceObject {} 

用多分派库扩展的语言

在不于语言定义或语法层次支持多分派的语言中,可能经常使用扩展来增加多分派。

JavaScript

JavaScriptTypeScript不在语言语法层次上支持多方法,但可以通过库来增加多分派。例如,使用multimethod包[9],它提供了多分派、泛化函数的实现。JavaScript的动态类型版本:

import { multi, method } from '@arrows/multimethod' class Asteroid {} class Spaceship {} const collideWith = multi( method([Asteroid, Asteroid], (x, y) => { // deal with asteroid hitting asteroid }), method([Asteroid, Spaceship], (x, y) => { // deal with asteroid hitting spaceship }), method([Spaceship, Asteroid], (x, y) => { // deal with spaceship hitting asteroid }), method([Spaceship, Spaceship], (x, y) => { // deal with spaceship hitting spaceship }), ) 

TypeScript有对应的静态类型版本。[a]

Python

可以使用扩展来向Python增加多分派。例如,最早的模块multimethods.py[10],它为Python提供了CLOS风格的多方法而不用变更语言的底层语法或关键字。在功能上,这非常类似于CLOS例子,但是语法是常规Python的。[b]Guido van Rossum使用Python 2.4介入的修饰器(decorator),出品了多方法的具有简化了的语法的一个简单实现,他为此定义了multimethod修饰器[11][c] multipledispatch[12]采用的形式与之一致。

模块multimethod[13],采用了修饰器和Python 3.5介入的类型提示实现多方法:

from multimethod import multimethod class Asteroid(): pass class Spaceship(): pass @multimethod def collide_with(x: Asteroid, y: Asteroid): '''deal with asteroid hitting asteroid''' print("asteroid hitting asteroid") @multimethod def collide_with(x: Asteroid, y: Spaceship): '''deal with asteroid hitting spaceship''' print("asteroid hitting spaceship") @multimethod def collide_with(x: Spaceship, y: Asteroid): '''deal with spaceship hitting asteroid''' print("spaceship hitting asteroid") @multimethod def collide_with(x: Spaceship, y: Spaceship): '''deal with spaceship hitting spaceship''' print("spaceship hitting spaceship") 
>>> a = Asteroid() >>> b = Spaceship() >>> collide_with(a, b) asteroid hitting spaceship 

此外,还有PEAK-Rules包提供语法类似上述例子的多分派[14],它后来被替代为PyProtocols[15]。Reg库也支持多分派和谓词分派[16]

C

C语言使用C Object System库[17],可以支持类似于CLOS的动态分派。它是完全可扩展的并且方法不需要任何的手工处理。动态消息(方法)通过COS分派器来分派,它比Objective-C更快。下面是使用COS的例子:

#include <stdio.h> #include <cos/Object.h> #include <cos/gen/object.h> /* 类 */ defclass (Asteroid) /* 数据成员 */ endclass defclass (Spaceship) /* 数据成员 */ endclass /* 泛化函数 */ defgeneric (_Bool, collide_with, _1, _2); /* 多方法 */ defmethod (_Bool, collide_with, Asteroid, Asteroid)  /* deal with asteroid hitting asteroid */ endmethod defmethod (_Bool, collide_with, Asteroid, Spaceship)  /* deal with asteroid hitting spaceship */ endmethod defmethod (_Bool, collide_with, Spaceship, Asteroid)  /* deal with spaceship hitting asteroid */ endmethod defmethod (_Bool, collide_with, Spaceship, Spaceship)  /* deal with spaceship hitting spaceship */ endmethod /* 用例 */ int main(int argc, char *argv[]) {  OBJ a = gnew(Asteroid);  OBJ s = gnew(Spaceship);  printf("<a,a> = %d\n", collide_with(a, a));  printf("<a,s> = %d\n", collide_with(a, s));  printf("<s,a> = %d\n", collide_with(s, a));  printf("<s,s> = %d\n", collide_with(s, s));  grelease(a);  grelease(s); } 

编程语言支持

主范型

支持通用的多方法

通过扩展

模拟多分派

C

C语言没有动态分派,也可以不使用C Object System库,而以某种形式手工实现。动态分派经常使用enum来标识一个对象的子类型,然后可通过在函数指针分支表英语branch table中查找这个值来完成。C语言模拟多方法的简单例子:

typedef void (*CollisionCase)(void); void collision_AA(void) { /* handle Asteroid-Asteroid collision */ }; void collision_AS(void) { /* handle Asteroid-Spaceship collision */ }; void collision_SA(void) { /* handle Spaceship-Asteroid collision */ }; void collision_SS(void) { /* handle Spaceship-Spaceship collision*/ }; typedef enum {  THING_ASTEROID = 0,  THING_SPACESHIP,  THING_COUNT /* not a type of thing itself, instead used to find number of things */ } Thing; CollisionCase collisionCases[THING_COUNT][THING_COUNT] = {  {&collision_AA, &collision_AS},  {&collision_SA, &collision_SS} }; void collide(Thing a, Thing b) {  (*collisionCases[a][b])(); } int main(void) {  collide(THING_SPACESHIP, THING_ASTEROID); } 

Java

在只有单一分派的语言比如Java中,多分派可以用多层单一分派来模拟:

interface Collideable { void collideWith(final Collideable other); /* These methods would need different names in a language without method overloading. */ void collideWith(final Asteroid asteroid); void collideWith(final Spaceship spaceship); } class Asteroid implements Collideable { public void collideWith(final Collideable other) { // Call collideWith on the other object. other.collideWith(this); } public void collideWith(final Asteroid asteroid) { // Handle Asteroid-Asteroid collision. } public void collideWith(final Spaceship spaceship) { // Handle Asteroid-Spaceship collision. } } class Spaceship implements Collideable { public void collideWith(final Collideable other) { // Call collideWith on the other object. other.collideWith(this); } public void collideWith(final Asteroid asteroid) { // Handle Spaceship-Asteroid collision. } public void collideWith(final Spaceship spaceship) { // Handle Spaceship-Spaceship collision. } } 

运行时间instanceof检查可以在一个或两个层次上使用。

代码示例

  1. ^ TypeScript的多方法示例:
    import { multi, method, Multi } from '@arrows/multimethod' class Asteroid {} class Spaceship {} type CollideWith = Multi & { (x: Asteroid, y: Asteroid): void (x: Asteroid, y: Spaceship): void (x: Spaceship, y: Asteroid): void (x: Spaceship, y: Spaceship): void } const collideWith: CollideWith = multi( method([Asteroid, Asteroid], (x, y) => { // deal with asteroid hitting asteroid }), method([Asteroid, Spaceship], (x, y) => { // deal with asteroid hitting spaceship }), method([Spaceship, Asteroid], (x, y) => { // deal with spaceship hitting asteroid }), method([Spaceship, Spaceship], (x, y) => { // deal with spaceship hitting spaceship }), ) 
  2. ^ Python的multimethods.py示例:
    from multimethods import Dispatch from game_objects import Asteroid, Spaceship from game_behaviors import as_func, ss_func, sa_func collide = Dispatch() collide.add_rule((Asteroid, Spaceship), as_func) collide.add_rule((Spaceship, Spaceship), ss_func) collide.add_rule((Spaceship, Asteroid), sa_func) def aa_func(a, b): """Behavior when asteroid hits asteroid.""" # ...define new behavior... collide.add_rule((Asteroid, Asteroid), aa_func) 
    # ...later... collide(thing1, thing2) 
  3. ^ Python的van Rossum最初的多方法实现:
    @multimethod(Asteroid, Asteroid) def collide(a, b): """Behavior when asteroid hits a asteroid.""" # ...define new behavior... @multimethod(Asteroid, Spaceship) def collide(a, b): """Behavior when asteroid hits a spaceship.""" # ...define new behavior... # ... define other multimethod rules ... 

引用

  1. ^ Ranka, Sanjay; Banerjee, Arunava; Biswas, Kanad Kishore; Dua, Sumeet; Mishra, Prabhat; Moona, Rajat. Contemporary Computing: Second International Conference, IC3 2010, Noida, India, August 9–11, 2010. Proceedings. Springer. 2010-07-26 [2021-03-23]. ISBN 9783642148248. (原始内容于2021-04-27). 
  2. ^ Igor Wojda. Programmer dictionary: Receiver. Kt.Academy. 2018-02-08 [2020-02-27] (英语). 
  3. ^ Bezanson, Jeff; Edelman, Alan; Karpinski, Stefan; Shah, Viral B. Julia: A fresh approach to numerical computing. SIAM Review. 7 February 2017, 59 (1): 65–98. arXiv:1411.1607 . doi:10.1137/141000671. 
  4. ^ Using type dynamic (C# Programming Guide). [2020-05-14]. (原始内容于2021-05-26). 
  5. ^ switch expression (C# reference). [2020-05-14]. (原始内容于2021-06-28). 
  6. ^ Basic concepts. [2020-05-14]. (原始内容于2021-04-16). 
  7. ^ Dynamic .NET - Understanding the Dynamic Keyword in C# 4. [2020-05-14]. (原始内容于2021-05-24). 
  8. ^ Groovy - Multi-methods. [2021-04-15]. (原始内容于2021-04-16). 
  9. ^ 9.0 9.1 9.2 @arrows/multimethod (页面存档备份,存于互联网档案馆) Multiple dispatch in JavaScript/TypeScript with configurable dispatch resolution by Maciej Cąderek.
  10. ^ multimethods.py (页面存档备份,存于互联网档案馆), Multiple dispatch in Python with configurable dispatch resolution by David Mertz, et al.
  11. ^ Five-minute Multimethods in Python. [2014-07-13]. (原始内容于2021-05-29). 
  12. ^ 12.0 12.1 multipledispatch. [2021-04-15]. (原始内容于2020-11-11). 
  13. ^ 13.0 13.1 Coady, Aric, multimethod: Multiple argument dispatching., [2021-01-28], (原始内容于2020-12-31) 
  14. ^ PEAK-Rules 0.5a1.dev. Python Package Index. [21 March 2014]. (原始内容于2017-03-14). 
  15. ^ PyProtocols. Python Enterprise Application Kit. [26 April 2019]. (原始内容于2021-05-05). 
  16. ^ 16.0 16.1 Reg. Read the docs. [26 April 2019]. (原始内容于2021-03-05). 
  17. ^ 17.0 17.1 C Object System: A framework that brings C to the level of other high level programming languages and beyond: CObjectSystem/COS. 2019-02-19 [2021-03-30]. (原始内容于2021-05-01). 
  18. ^ . The Julia Manual. Julialang. [11 May 2014]. (原始内容存档于2016-07-17). 
  19. ^ Multimethods in C# 4.0 With 'Dynamic'. [2009-08-20]. (原始内容于2009-08-25). 
  20. ^ Cecil Language. [2008-04-13]. (原始内容于2016-09-01). 
  21. ^ Multimethods in Clojure. [2008-09-04]. (原始内容于2015-09-20). 
  22. ^ Steele, Guy L. 28. Common LISP: The Language. Bedford, MA, U.S.A: Digital Press. 1990 [2021-03-30]. ISBN 978-1-55558-041-4. (原始内容于2017-12-17). 
  23. ^ Background and Goals. [2008-04-13]. (原始内容于2020-04-04). 
  24. ^ (PDF). [2010-04-23]. (原始内容 (PDF)存档于2013-01-20). 
  25. ^ Multimethods in Groovy. [2008-04-13]. (原始内容于2011-08-12). 
  26. ^ Methods – LassoGuide 9.2. [2014-11-11]. (原始内容于2021-06-13). 
  27. ^ Visitor Pattern Versus Multimethods. [2008-04-13]. (原始内容于2021-02-05). 
  28. ^ Nim Manual: Multi-methods. [2020-09-11]. (原始内容于2021-06-15). 
  29. ^ Perl 6 FAQ. [2008-04-13]. (原始内容于2012-03-13). 
  30. ^ How S4 Methods Work (PDF). [2008-04-13]. (原始内容 (PDF)于2021-05-10). 
  31. ^ Multiple Dispatch in Seed7. [2011-04-23]. (原始内容于2021-01-29). 
  32. ^ TADS 3 System Manual. [2012-03-19]. (原始内容于2017-02-14). 
  33. ^ VB.Net Multiple Dispatch. [2020-03-31]. (原始内容于2021-04-11). 
  34. ^ New Features in C#4.0 and VB.Net 10.0. [2020-03-31]. (原始内容于2021-02-01). 
  35. ^ Notes for Programming Language Experts. [2016-08-21]. (原始内容于2021-06-26). 
  36. ^ Multiple dispatch. [2021-03-30]. (原始内容于2021-05-08). 
  37. ^ MultiMethods.NET. [2014-07-13]. (原始内容于2010-02-26). 
  38. ^ multimethod-sharp. [2021-03-30]. (原始内容于2016-01-23). 
  39. ^ yomm2. [2021-03-30]. (原始内容于2020-11-12). 
  40. ^ multimethods. [2021-03-30]. (原始内容于2020-11-22). 
  41. ^ openmethods
  42. ^ multimethods vocabulary. [2014-07-13]. (原始内容于2021-04-29). 
  43. ^ MultiJava. [2014-07-13]. (原始内容于2021-04-11). 
  44. ^ Class::Multimethods. [2014-07-13]. (原始内容于2013-10-21). 
  45. ^ multimethod-lib. [2021-03-30]. (原始内容于2021-04-29). 
  46. ^ The Multiple Dispatch Library. [2021-03-30]. (原始内容于2021-04-30). 
  47. ^ Multimethod Package. [2021-03-30]. (原始内容于2021-04-29). 
  48. ^ Vlx-Multimethods Package. [2021-03-30]. (原始内容于2021-04-27). 
  49. ^ TinyCLOS. [2014-07-13]. (原始内容于2008-12-11). 

外部链接

  • Stroustrup, Bjarne; Solodkyy, Yuriy; Pirkelbauer, Peter. Open Multi-Methods for C++ (PDF). ACM 6th International Conference on Generative Programming and Component Engineering. 2007 [2014-07-13]. (原始内容 (PDF)于2021-04-29). 
  • Dynamic multiple dispatch. docs.racket-lang.org. [2018-03-12]. (原始内容于2021-04-29). 

多分派, 或译多重派发, multiple, dispatch, 或多方法, multimethod, 是某些编程语言的一个特性, 其中的函数或者方法, 可以在运行时间, 动态的, 基于它的实际参数的类型, 或在更一般的情况下于此之外的其他特性, 来动态分派, 这是对单分派多态的推广, 那里的函数或方法调用, 基于在其上调用方法的对象的派生类型, 而动态分派, 使用一个或多个实际参数的组合特征, 路由动态分派至实现函数或方法, 目录, 理解分派, 数据类型, 例子, 具有内建的语言, common, lisp, j. 多分派或译多重派发 multiple dispatch 或多方法 multimethod 是某些编程语言的一个特性 其中的函数或者方法 可以在运行时间 动态的 基于它的实际参数的类型 或在更一般的情况下于此之外的其他特性 来动态分派 1 这是对单分派多态的推广 那里的函数或方法调用 基于在其上调用方法的对象的派生类型 而动态分派 多分派使用一个或多个实际参数的组合特征 路由动态分派至实现函数或方法 目录 1 理解分派 1 1 数据类型 2 例子 2 1 具有内建多分派的语言 2 1 1 Common Lisp 2 1 2 Julia 2 1 3 C 2 1 4 Groovy 2 2 用多分派库扩展的语言 2 2 1 JavaScript 2 2 2 Python 2 2 3 C 3 编程语言支持 3 1 主范型 3 2 支持通用的多方法 3 3 通过扩展 4 模拟多分派 4 1 C 4 2 Java 5 代码示例 6 引用 7 外部链接理解分派 编辑软件工程师通常把代码写进代码块中 代码块通常称作过程 函数 方法 代码通过被调用来执行 调用时将控制权传入函数中 当函数执行完成后将控制权返回给调用者 函数名通常用来描述函数的目的 有时会将多个函数起同样的名称 比如同名函数在逻辑上处理相同的任务 但是操作在不同类型的输入值上 在这种情况下 无法仅仅通过函数名 来判断目标代码块 那么 函数的实际参数的个数和类型 也就被用来判断 通常 单分派面向对象语言 在调用一个方法时 方法参数中一个参数会被特殊对待 并用来决定哪一个方法 如果有多个同名方法 会被调用 在许多语言中 这个特殊的参数是在语法上指明的 许多编程语言在调用方法时 把特殊参数放在小圆点 之前 例如 special method other arguments here 这样 lion sound 将会发出狮吼 同时 sparrow sound 只会吱吱地叫 一般来说 对于面向对象的编程语言 这个小圆点之前的参数 上例中的lion和sparrow 被称为接收者 2 相反 在实现了多分派的语言中 被调用的函数 即是那些参数个数一样多 并且类型也匹配的调用 在调用中并没有特殊参数 来决定那个方法被调用 也就是说 所有参数的运行时类型都参与分派 CLOS是早期和著名的多分派语言 数据类型 编辑 对于编译时间可以区分数据类型的编程语言 在交替 英语 Alternation formal language theory alternative 函数中进行选择 可以发生在编译时间 创建交替函数用于编译时间选择的活动 通常被叫做函数重载 在有些编程语言中 这种数据类型的识别 可以被延后至运行时间 后期绑定 英语 Late binding 交替函数的选择发生在运行时间 并依据动态确定的函数实际参数的类型 以这种方式选择交替实现的函数 通常被称为多方法 例子 编辑可以通过例子更加清晰的区分多分派和单一分派 假想一个游戏 它有两种 用户可见的 物体 飞船和小行星 当两个物体要相撞的时候 程序需要依据什么物体要相撞而做不同的事情 具有内建多分派的语言 编辑 Common Lisp 编辑 在具有多分派的Common Lisp语言中 可以在Common Lisp对象系统中如下这样实现 defgeneric collide x y defclass asteroid defclass spaceship defmethod collide with x asteroid y asteroid deal with asteroid hitting asteroid defmethod collide with x asteroid y spaceship deal with asteroid hitting spaceship defmethod collide with x spaceship y asteroid deal with spaceship hitting asteroid defmethod collide with x spaceship y spaceship deal with spaceship hitting spaceship 并且对其他方法也是类似的 没有使用显式测试和 动态转换 由于多分派的存在 方法要定义在类中并包含在对象中的传统想法 变得不再吸引人了 上述每个collide with方法 都附属于两个不同的类而非一个类 因此方法调用的特殊语法 一般会消失 从而方法调用看起来完全就像正常的函数调用 并且方法被组织入泛化函数而非类中 Julia 编辑 Julia有内建的多分派 并且它是语言设计的中心 3 Julia版本的例子如下 collide with x Asteroid y Asteroid deal with asteroid hitting asteroid collide with x Asteroid y Spaceship deal with asteroid hitting spaceship collide with x Spaceship y Asteroid deal with spaceship hitting asteroid collide with x Spaceship y Spaceship deal with spaceship hitting spaceship C 编辑 C 在版本4 2010年4月 使用关键字dynamic 介入了对动态多方法的支持 4 下面的例子展示多方法协同于在版本8 2019年9月 中介入的switch表达式 5 像很多其他静态类型的语言语言一样 C 还支持静态方法重载 6 Microsoft预期开发者在多数场景下会选用静态类型超过动态类型 7 dynamic关键字支持COM对象和动态类型的 NET语言的互操作 class Program static void Main Console WriteLine Collider Collide new Asteroid 101 new Spaceship 300 Console WriteLine Collider Collide new Asteroid 10 new Spaceship 10 Console WriteLine Collider Collide new Spaceship 101 new Spaceship 10 static class Collider public static string Collide SpaceObject x SpaceObject y gt x Size gt 100 amp amp y Size gt 100 Big boom CollideWith x as dynamic y as dynamic private static string CollideWith Asteroid x Asteroid y gt a a private static string CollideWith Asteroid x Spaceship y gt a s private static string CollideWith Spaceship x Asteroid y gt s a private static string CollideWith Spaceship x Spaceship y gt s s abstract class SpaceObject public SpaceObject int size gt Size size public int Size get class Asteroid SpaceObject public Asteroid int size base size class Spaceship SpaceObject public Spaceship int size base size 输出 big boom a s s s Groovy 编辑 Groovy是通用的Java兼容 互用的JVM语言 它对立于Java 使用后期绑定 多分派 8 Groovy implementation of C example above Late binding works the same when using non static methods or compiling class methods statically CompileStatic annotation class Program static void main String args println Collider collide new Asteroid 101 new Spaceship 300 println Collider collide new Asteroid 10 new Spaceship 10 println Collider collide new Spaceship 101 new Spaceship 10 class Collider static String collide SpaceObject x SpaceObject y x size gt 100 amp amp y size gt 100 big boom collideWith x y Dynamic dispatch to collideWith method private static String collideWith Asteroid x Asteroid y a a private static String collideWith Asteroid x Spaceship y a s private static String collideWith Spaceship x Asteroid y s a private static String collideWith Spaceship x Spaceship y s s class SpaceObject int size SpaceObject int size this size size InheritConstructors class Asteroid extends SpaceObject InheritConstructors class Spaceship extends SpaceObject 用多分派库扩展的语言 编辑 在不于语言定义或语法层次支持多分派的语言中 可能经常使用库扩展来增加多分派 JavaScript 编辑 JavaScript和TypeScript不在语言语法层次上支持多方法 但可以通过库来增加多分派 例如 使用multimethod包 9 它提供了多分派 泛化函数的实现 JavaScript的动态类型版本 import multi method from arrows multimethod class Asteroid class Spaceship const collideWith multi method Asteroid Asteroid x y gt deal with asteroid hitting asteroid method Asteroid Spaceship x y gt deal with asteroid hitting spaceship method Spaceship Asteroid x y gt deal with spaceship hitting asteroid method Spaceship Spaceship x y gt deal with spaceship hitting spaceship TypeScript有对应的静态类型版本 a Python 编辑 可以使用库扩展来向Python增加多分派 例如 最早的模块multimethods py 10 它为Python提供了CLOS风格的多方法而不用变更语言的底层语法或关键字 在功能上 这非常类似于CLOS例子 但是语法是常规Python的 b Guido van Rossum使用Python 2 4介入的修饰器 decorator 出品了多方法的具有简化了的语法的一个简单实现 他为此定义了multimethod修饰器 11 c multipledispatch 12 采用的形式与之一致 模块multimethod 13 采用了修饰器和Python 3 5介入的类型提示实现多方法 from multimethod import multimethod class Asteroid pass class Spaceship pass multimethod def collide with x Asteroid y Asteroid deal with asteroid hitting asteroid print asteroid hitting asteroid multimethod def collide with x Asteroid y Spaceship deal with asteroid hitting spaceship print asteroid hitting spaceship multimethod def collide with x Spaceship y Asteroid deal with spaceship hitting asteroid print spaceship hitting asteroid multimethod def collide with x Spaceship y Spaceship deal with spaceship hitting spaceship print spaceship hitting spaceship gt gt gt a Asteroid gt gt gt b Spaceship gt gt gt collide with a b asteroid hitting spaceship 此外 还有PEAK Rules包提供语法类似上述例子的多分派 14 它后来被替代为PyProtocols 15 Reg库也支持多分派和谓词分派 16 C 编辑 C语言使用C Object System库 17 可以支持类似于CLOS的动态分派 它是完全可扩展的并且方法不需要任何的手工处理 动态消息 方法 通过COS分派器来分派 它比Objective C更快 下面是使用COS的例子 include lt stdio h gt include lt cos Object h gt include lt cos gen object h gt 类 defclass Asteroid 数据成员 endclass defclass Spaceship 数据成员 endclass 泛化函数 defgeneric Bool collide with 1 2 多方法 defmethod Bool collide with Asteroid Asteroid deal with asteroid hitting asteroid endmethod defmethod Bool collide with Asteroid Spaceship deal with asteroid hitting spaceship endmethod defmethod Bool collide with Spaceship Asteroid deal with spaceship hitting asteroid endmethod defmethod Bool collide with Spaceship Spaceship deal with spaceship hitting spaceship endmethod 用例 int main int argc char argv OBJ a gnew Asteroid OBJ s gnew Spaceship printf lt a a gt d n collide with a a printf lt a s gt d n collide with a s printf lt s a gt d n collide with s a printf lt s s gt d n collide with s s grelease a grelease s 编程语言支持 编辑主范型 编辑 Julia 18 支持通用的多方法 编辑 C 4 0 英语 C 4 0 19 Cecil 英语 Cecil programming language 20 Clojure 21 Common Lisp 通过Common Lisp对象系统 22 Dylan 23 Fortress 英语 Fortress programming language 24 Groovy 25 Lasso 英语 Lasso programming language 26 27 Nim 在v0 20之后泛化方法被废止 使用多方法需要加编译指令 28 Raku 29 R 30 Seed7 英语 Seed7 31 TADS 英语 TADS 32 VB Net 33 通过后期绑定 还通过 Net DLR 34 Wolfram语言 35 通过符号模式匹配 Xtend 英语 Xtend 36 通过扩展 编辑 任何 NET语言 通过库MultiMethods NET 37 C 通过库C Object System 17 C 通过库multimethod sharp 38 C 通过库yomm2 39 和multimethods 40 D 通过库openmethods 41 Factor 通过标准multimethods词汇表 42 Java 使用扩展MultiJava 43 JavaScript 通过包 arrows multimethod 9 Perl 通过模块Class Multimethods 44 Python 模块multimethod 13 multipledispatch 12 或Reg库 16 Racket 通过库multimethod lib 45 Ruby 通过Multiple Dispatch库 46 Multimethod包 47 和Vlx Multimethods包 48 Scheme 通过TinyCLOS 49 TypeScript 通过包 arrows multimethod 9 模拟多分派 编辑C 编辑 C语言没有动态分派 也可以不使用C Object System库 而以某种形式手工实现 动态分派经常使用enum来标识一个对象的子类型 然后可通过在函数指针分支表 英语 branch table 中查找这个值来完成 C语言模拟多方法的简单例子 typedef void CollisionCase void void collision AA void handle Asteroid Asteroid collision void collision AS void handle Asteroid Spaceship collision void collision SA void handle Spaceship Asteroid collision void collision SS void handle Spaceship Spaceship collision typedef enum THING ASTEROID 0 THING SPACESHIP THING COUNT not a type of thing itself instead used to find number of things Thing CollisionCase collisionCases THING COUNT THING COUNT amp collision AA amp collision AS amp collision SA amp collision SS void collide Thing a Thing b collisionCases a b int main void collide THING SPACESHIP THING ASTEROID Java 编辑 在只有单一分派的语言比如Java中 多分派可以用多层单一分派来模拟 interface Collideable void collideWith final Collideable other These methods would need different names in a language without method overloading void collideWith final Asteroid asteroid void collideWith final Spaceship spaceship class Asteroid implements Collideable public void collideWith final Collideable other Call collideWith on the other object other collideWith this public void collideWith final Asteroid asteroid Handle Asteroid Asteroid collision public void collideWith final Spaceship spaceship Handle Asteroid Spaceship collision class Spaceship implements Collideable public void collideWith final Collideable other Call collideWith on the other object other collideWith this public void collideWith final Asteroid asteroid Handle Spaceship Asteroid collision public void collideWith final Spaceship spaceship Handle Spaceship Spaceship collision 运行时间instanceof检查可以在一个或两个层次上使用 代码示例 编辑 TypeScript的多方法示例 import multi method Multi from arrows multimethod class Asteroid class Spaceship type CollideWith Multi amp x Asteroid y Asteroid void x Asteroid y Spaceship void x Spaceship y Asteroid void x Spaceship y Spaceship void const collideWith CollideWith multi method Asteroid Asteroid x y gt deal with asteroid hitting asteroid method Asteroid Spaceship x y gt deal with asteroid hitting spaceship method Spaceship Asteroid x y gt deal with spaceship hitting asteroid method Spaceship Spaceship x y gt deal with spaceship hitting spaceship Python的multimethods py示例 from multimethods import Dispatch from game objects import Asteroid Spaceship from game behaviors import as func ss func sa func collide Dispatch collide add rule Asteroid Spaceship as func collide add rule Spaceship Spaceship ss func collide add rule Spaceship Asteroid sa func def aa func a b Behavior when asteroid hits asteroid define new behavior collide add rule Asteroid Asteroid aa func later collide thing1 thing2 Python的van Rossum最初的多方法实现 multimethod Asteroid Asteroid def collide a b Behavior when asteroid hits a asteroid define new behavior multimethod Asteroid Spaceship def collide a b Behavior when asteroid hits a spaceship define new behavior define other multimethod rules 引用 编辑 Ranka Sanjay Banerjee Arunava Biswas Kanad Kishore Dua Sumeet Mishra Prabhat Moona Rajat Contemporary Computing Second International Conference IC3 2010 Noida India August 9 11 2010 Proceedings Springer 2010 07 26 2021 03 23 ISBN 9783642148248 原始内容存档于2021 04 27 Igor Wojda Programmer dictionary Receiver Kt Academy 2018 02 08 2020 02 27 英语 Bezanson Jeff Edelman Alan Karpinski Stefan Shah Viral B Julia A fresh approach to numerical computing SIAM Review 7 February 2017 59 1 65 98 arXiv 1411 1607 doi 10 1137 141000671 Using type dynamic C Programming Guide 2020 05 14 原始内容存档于2021 05 26 switch expression C reference 2020 05 14 原始内容存档于2021 06 28 Basic concepts 2020 05 14 原始内容存档于2021 04 16 Dynamic NET Understanding the Dynamic Keyword in C 4 2020 05 14 原始内容存档于2021 05 24 Groovy Multi methods 2021 04 15 原始内容存档于2021 04 16 9 0 9 1 9 2 arrows multimethod 页面存档备份 存于互联网档案馆 Multiple dispatch in JavaScript TypeScript with configurable dispatch resolution by Maciej Caderek multimethods py 页面存档备份 存于互联网档案馆 Multiple dispatch in Python with configurable dispatch resolution by David Mertz et al Five minute Multimethods in Python 2014 07 13 原始内容存档于2021 05 29 12 0 12 1 multipledispatch 2021 04 15 原始内容存档于2020 11 11 13 0 13 1 Coady Aric multimethod Multiple argument dispatching 2021 01 28 原始内容存档于2020 12 31 PEAK Rules 0 5a1 dev Python Package Index 21 March 2014 原始内容存档于2017 03 14 PyProtocols Python Enterprise Application Kit 26 April 2019 原始内容存档于2021 05 05 16 0 16 1 Reg Read the docs 26 April 2019 原始内容存档于2021 03 05 17 0 17 1 C Object System A framework that brings C to the level of other high level programming languages and beyond CObjectSystem COS 2019 02 19 2021 03 30 原始内容存档于2021 05 01 Methods The Julia Manual Julialang 11 May 2014 原始内容存档于2016 07 17 Multimethods in C 4 0 With Dynamic 2009 08 20 原始内容存档于2009 08 25 Cecil Language 2008 04 13 原始内容存档于2016 09 01 Multimethods in Clojure 2008 09 04 原始内容存档于2015 09 20 Steele Guy L 28 Common LISP The Language Bedford MA U S A Digital Press 1990 2021 03 30 ISBN 978 1 55558 041 4 原始内容存档于2017 12 17 Background and Goals 2008 04 13 原始内容存档于2020 04 04 The Fortress Language Specification Version 1 0 PDF 2010 04 23 原始内容 PDF 存档于2013 01 20 Multimethods in Groovy 2008 04 13 原始内容存档于2011 08 12 Methods LassoGuide 9 2 2014 11 11 原始内容存档于2021 06 13 Visitor Pattern Versus Multimethods 2008 04 13 原始内容存档于2021 02 05 Nim Manual Multi methods 2020 09 11 原始内容存档于2021 06 15 Perl 6 FAQ 2008 04 13 原始内容存档于2012 03 13 How S4 Methods Work PDF 2008 04 13 原始内容存档 PDF 于2021 05 10 Multiple Dispatch in Seed7 2011 04 23 原始内容存档于2021 01 29 TADS 3 System Manual 2012 03 19 原始内容存档于2017 02 14 VB Net Multiple Dispatch 2020 03 31 原始内容存档于2021 04 11 New Features in C 4 0 and VB Net 10 0 2020 03 31 原始内容存档于2021 02 01 Notes for Programming Language Experts 2016 08 21 原始内容存档于2021 06 26 Multiple dispatch 2021 03 30 原始内容存档于2021 05 08 MultiMethods NET 2014 07 13 原始内容存档于2010 02 26 multimethod sharp 2021 03 30 原始内容存档于2016 01 23 yomm2 2021 03 30 原始内容存档于2020 11 12 multimethods 2021 03 30 原始内容存档于2020 11 22 openmethods multimethods vocabulary 2014 07 13 原始内容存档于2021 04 29 MultiJava 2014 07 13 原始内容存档于2021 04 11 Class Multimethods 2014 07 13 原始内容存档于2013 10 21 multimethod lib 2021 03 30 原始内容存档于2021 04 29 The Multiple Dispatch Library 2021 03 30 原始内容存档于2021 04 30 Multimethod Package 2021 03 30 原始内容存档于2021 04 29 Vlx Multimethods Package 2021 03 30 原始内容存档于2021 04 27 TinyCLOS 2014 07 13 原始内容存档于2008 12 11 外部链接 编辑Stroustrup Bjarne Solodkyy Yuriy Pirkelbauer Peter Open Multi Methods for C PDF ACM 6th International Conference on Generative Programming and Component Engineering 2007 2014 07 13 原始内容存档 PDF 于2021 04 29 Dynamic multiple dispatch docs racket lang org 2018 03 12 原始内容存档于2021 04 29 取自 https zh wikipedia org w index php title 多分派 amp oldid 70245350, 维基百科,wiki,书籍,书籍,图书馆,

文章

,阅读,下载,免费,免费下载,mp3,视频,mp4,3gp, jpg,jpeg,gif,png,图片,音乐,歌曲,电影,书籍,游戏,游戏。