FazBrowse Wikipedia Viewer | Main Page |
Search Wikipedia:
|
Viewing: https://en.wikipedia.org/wiki/Multiple_dispatch

Multiple dispatch

Contents
        Groovy
        Common Lisp
        Julia
        Raku
    Extending languages with multiple-dispatch libraries
        JavaScript
        Python
    Emulating multiple dispatch
        C
        C++
        D

Polymorphism
Ad hoc polymorphism
Parametric polymorphism
Subtyping
Big boom! a/s s/s

Groovy

edit

Groovy is a general purpose Java compatible/interusable JVM language, which, contrary to Java, uses late binding / multiple dispatch.

100 && y.size > 100) ? \"big-boom\" : collideWith(x, y) // Dynamic dispatch to collideWith method\n }\n\n private static String collideWith(Asteroid x, Asteroid y) { \"a/a\" }\n private static String collideWith(Asteroid x, Spaceship y) { \"a/s\" }\n private static String collideWith(Spaceship x, Asteroid y) { \"s/a\" }\n private static String collideWith(Spaceship x, Spaceship y) { \"s/s\"}\n}\n\nclass SpaceObject {\n int size\n SpaceObject(int size) { this.size = size }\n}\n\n@InheritConstructors class Asteroid extends SpaceObject {}\n@InheritConstructors class Spaceship extends SpaceObject {}\n"}}'>/* Groovy implementation of C# example above Late binding works the same when using non-static methods or compiling class/methods statically (@CompileStatic annotation) */ classProgram{ staticvoidmain(String[]args){ printlnCollider.collide(newAsteroid(101),newSpaceship(300)) printlnCollider.collide(newAsteroid(10),newSpaceship(10)) printlnCollider.collide(newSpaceship(101),newSpaceship(10)) } } classCollider{ staticStringcollide(SpaceObjectx,SpaceObjecty){ (x.size>100&&y.size>100)?"big-boom":collideWith(x,y)// Dynamic dispatch to collideWith method } privatestaticStringcollideWith(Asteroidx,Asteroidy){"a/a"} privatestaticStringcollideWith(Asteroidx,Spaceshipy){"a/s"} privatestaticStringcollideWith(Spaceshipx,Asteroidy){"s/a"} privatestaticStringcollideWith(Spaceshipx,Spaceshipy){"s/s"} } classSpaceObject{ intsize SpaceObject(intsize){this.size=size} } @InheritConstructorsclassAsteroidextendsSpaceObject{} @InheritConstructorsclassSpaceshipextendsSpaceObject{}

Common Lisp

edit

In a language with multiple dispatch, such as Common Lisp, it might look more like this (Common Lisp example shown):

(size x) 100) (> (size y) 100))\n \"big-boom\"\n (collide-with x y)))\n\n(print (collide (space-object 'asteroid 101) (space-object 'spaceship 300)))\n(print (collide (space-object 'asteroid 10) (space-object 'spaceship 10)))\n(print (collide (space-object 'spaceship 101) (space-object 'spaceship 10)))\n"}}'>(defclassasteroid()((size:readersize:initarg:size))) (defclassspaceship()((size:readersize:initarg:size))) (defunspace-object(classsize)(make-instanceclass:sizesize)) ; collide-with is a generic function with multiple dispatch (defmethodcollide-with((xasteroid)(yasteroid))"a/a") (defmethodcollide-with((xasteroid)(yspaceship))"a/s") (defmethodcollide-with((xspaceship)(yasteroid))"s/a") (defmethodcollide-with((xspaceship)(yspaceship))"s/s") (defuncollide(xy) (if(and(>(sizex)100)(>(sizey)100)) "big-boom" (collide-withxy))) (print(collide(space-object'asteroid101)(space-object'spaceship300))) (print(collide(space-object'asteroid10)(space-object'spaceship10))) (print(collide(space-object'spaceship101)(space-object'spaceship10)))

and similarly for the other methods. Explicit testing and "dynamic casting" are not used.

In the presence of multiple dispatch, the traditional idea of methods as being defined in classes and contained in objects becomes less appealing—each collide-with method above is attached to two different classes, not one. Hence, the special syntax for method invocation generally disappears, so that method invocation looks exactly like ordinary function invocation, and methods are grouped not in classes but in generic functions.

Julia

edit

Julia has built-in multiple dispatch, and it is central to the language design. The Julia version of the example above might look like:

100 && y.size > 100) ? \"Big boom!\" : collide_with(x, y)\n"}}'>abstracttype SpaceObjectend struct Asteroid<:SpaceObject size::Int end struct Spaceship<:SpaceObject size::Int end collide_with(::Asteroid,::Spaceship)="a/s" collide_with(::Spaceship,::Asteroid)="s/a" collide_with(::Spaceship,::Spaceship)="s/s" collide_with(::Asteroid,::Asteroid)="a/a" collide(x::SpaceObject,y::SpaceObject)=(x.size>100&&y.size>100)?"Big boom!":collide_with(x,y)

Output:

collide(Asteroid(101), Spaceship(300))\n\"Big boom!\"\n\njulia> collide(Asteroid(10), Spaceship(10))\n\"a/s\"\n\njulia> collide(Spaceship(101), Spaceship(10))\n\"s/s\"\n"}}'>julia>collide(Asteroid(101),Spaceship(300)) "Big boom!" julia>collide(Asteroid(10),Spaceship(10)) "a/s" julia>collide(Spaceship(101),Spaceship(10)) "s/s"

Raku

edit

Raku, like Perl, uses proven ideas from other languages, and type systems have shown themselves to offer compelling advantages in compiler-side code analysis and powerful user-side semantics via multiple dispatch.

It has both multimethods, and multisubs. Since most operators are subroutines, it also has multiple dispatched operators.

Along with the usual type constraints, it also has where constraints that allow making very specialized subroutines.

;\nmy Str @damaged = « damaged 'collided with' 'was damaged by' »;\n\n# We add multi candidates to the numeric comparison operators because we are comparing them numerically,\n# but makes no sense to have the objects coerce to a Numeric type.\n# ( If they did coerce we wouldn't necessarily need to add these operators. )\n# We could have also defined entirely new operators this same way.\nmulti sub infix:« <=> » ( Stellar-Object:D $a, Stellar-Object:D $b ) { $a.mass <=> $b.mass }\nmulti sub infix:« < » ( Stellar-Object:D $a, Stellar-Object:D $b ) { $a.mass < $b.mass }\nmulti sub infix:« > » ( Stellar-Object:D $a, Stellar-Object:D $b ) { $a.mass > $b.mass }\nmulti sub infix:« == » ( Stellar-Object:D $a, Stellar-Object:D $b ) { $a.mass == $b.mass }\n\n# Define a new multi dispatcher, and add some type constraints to the parameters.\n# If we didn't define it we would have gotten a generic one that didn't have constraints.\nproto sub collide ( Stellar-Object:D $, Stellar-Object:D $ ) {*}\n\n# No need to repeat the types here since they are the same as the prototype.\n# The 'where' constraint technically only applies to $b not the whole signature.\n# Note that the 'where' constraint uses the `<` operator candidate we added earlier.\nmulti sub collide ( $a, $b where $a < $b ) {\n say \"$a.name() was @destroyed.pick() by $b.name()\";\n}\nmulti sub collide ( $a, $b where $a > $b ) {\n # redispatch to the previous candidate with the arguments swapped\n samewith $b, $a;\n}\n\n# This has to be after the first two because the other ones\n# have 'where' constraints, which get checked in the\n# order the subs were written. ( This one would always match. )\nmulti sub collide ( $a, $b ) {\n # randomize the order\n my ($n1, $n2) = ( $a.name, $b.name ).pick(*);\n say \"$n1 @damaged.pick() $n2\";\n}\n\n# The following two candidates can be anywhere after the proto,\n# because they have more specialized types than the preceding three.\n\n# If the ships have unequal mass one of the first two candidates gets called instead.\nmulti sub collide ( Spaceship $a, Spaceship $b where $a == $b ){\n my ($n1, $n2) = ( $a.name, $b.name ).pick(*);\n say \"$n1 collided with $n2, and both ships were \",\n ( @destroyed.pick, 'left damaged' ).pick;\n}\n\n# You can unpack the attributes into variables within the signature.\n# You could even have a constraint on them `(:mass($a) where 10)`.\nmulti sub collide ( Asteroid $ (:mass($a)), Asteroid $ (:mass($b)) ){\n say \"two asteroids collided and combined into one larger asteroid of mass { $a + $b }\";\n}\n\nmy Spaceship $Enterprise .= new(:mass(1),:name('The Enterprise'));\ncollide Asteroid.new(:mass(.1)), $Enterprise;\ncollide $Enterprise, Spaceship.new(:mass(.1));\ncollide $Enterprise, Asteroid.new(:mass(1));\ncollide $Enterprise, Spaceship.new(:mass(1));\ncollide Asteroid.new(:mass(10)), Asteroid.new(:mass(5));\n"}}'>subset Mass of Real where 0 ^..^ Inf; role Stellar-Object { has Mass $.mass is required; method name () returns Str {...}; } class Asteroid does Stellar-Object { method name () { 'an asteroid' } } class Spaceship does Stellar-Object { has Str $.name = 'some unnamed spaceship'; } my Str @destroyed = < obliterated destroyed mangled >; my Str @damaged = « damaged 'collided with' 'was damaged by' »; # We add multi candidates to the numeric comparison operators because we are comparing them numerically, # but makes no sense to have the objects coerce to a Numeric type. # ( If they did coerce we wouldn't necessarily need to add these operators. ) # We could have also defined entirely new operators this same way. multi sub infix:« <=> » ( Stellar-Object:D $a, Stellar-Object:D $b ) { $a.mass <=> $b.mass } multi sub infix:« < » ( Stellar-Object:D $a, Stellar-Object:D $b ) { $a.mass < $b.mass } multi sub infix:« > » ( Stellar-Object:D $a, Stellar-Object:D $b ) { $a.mass > $b.mass } multi sub infix:« == » ( Stellar-Object:D $a, Stellar-Object:D $b ) { $a.mass == $b.mass } # Define a new multi dispatcher, and add some type constraints to the parameters. # If we didn't define it we would have gotten a generic one that didn't have constraints. proto sub collide ( Stellar-Object:D $, Stellar-Object:D $ ) {*} # No need to repeat the types here since they are the same as the prototype. # The 'where' constraint technically only applies to $b not the whole signature. # Note that the 'where' constraint uses the `<` operator candidate we added earlier. multi sub collide ( $a, $b where $a < $b ) { say "$a.name() was @destroyed.pick() by $b.name()"; } multi sub collide ( $a, $b where $a > $b ) { # redispatch to the previous candidate with the arguments swapped samewith $b, $a; } # This has to be after the first two because the other ones # have 'where' constraints, which get checked in the # order the subs were written. ( This one would always match. ) multi sub collide ( $a, $b ) { # randomize the order my ($n1, $n2) = ( $a.name, $b.name ).pick(*); say "$n1 @damaged.pick() $n2"; } # The following two candidates can be anywhere after the proto, # because they have more specialized types than the preceding three. # If the ships have unequal mass one of the first two candidates gets called instead. multi sub collide ( Spaceship $a, Spaceship $b where $a == $b ){ my ($n1, $n2) = ( $a.name, $b.name ).pick(*); say "$n1 collided with $n2, and both ships were ", ( @destroyed.pick, 'left damaged' ).pick; } # You can unpack the attributes into variables within the signature. # You could even have a constraint on them `(:mass($a) where 10)`. multi sub collide ( Asteroid $ (:mass($a)), Asteroid $ (:mass($b)) ){ say "two asteroids collided and combined into one larger asteroid of mass { $a + $b }"; } my Spaceship $Enterprise .= new(:mass(1),:name('The Enterprise')); collide Asteroid.new(:mass(.1)), $Enterprise; collide $Enterprise, Spaceship.new(:mass(.1)); collide $Enterprise, Asteroid.new(:mass(1)); collide $Enterprise, Spaceship.new(:mass(1)); collide Asteroid.new(:mass(10)), Asteroid.new(:mass(5));

Extending languages with multiple-dispatch libraries

edit

JavaScript

edit

In languages that do not support multiple dispatch at the language definition or syntactic level, it is often possible to add multiple dispatch using a library extension. JavaScript and TypeScript do not support multimethods at the syntax level, but it is possible to add multiple dispatch via a library. For example, the multimethod package provides an implementation of multiple dispatch, generic functions.

Dynamically-typed version in JavaScript:

{\n // deal with asteroid hitting asteroid\n }),\n method([Asteroid, Spaceship], (x, y) => {\n // deal with asteroid hitting spaceship\n }),\n method([Spaceship, Asteroid], (x, y) => {\n // deal with spaceship hitting asteroid\n }),\n method([Spaceship, Spaceship], (x, y) => {\n // deal with spaceship hitting spaceship\n }),\n)\n"}}'>import{multi,method}from'@arrows/multimethod' classAsteroid{} classSpaceship{} constcollideWith=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 }), )

Statically-typed version in TypeScript:

{\n // deal with asteroid hitting asteroid\n }),\n method([Asteroid, Spaceship], (x, y) => {\n // deal with asteroid hitting spaceship\n }),\n method([Spaceship, Asteroid], (x, y) => {\n // deal with spaceship hitting asteroid\n }),\n method([Spaceship, Spaceship], (x, y) => {\n // deal with spaceship hitting spaceship\n }),\n)\n"}}'>import{multi,method,Multi}from'@arrows/multimethod' classAsteroid{} classSpaceship{} typeCollideWith=Multi&{ (x:Asteroid,y:Asteroid):void (x:Asteroid,y:Spaceship):void (x:Spaceship,y:Asteroid):void (x:Spaceship,y:Spaceship):void } constcollideWith: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 }), )

Python

edit

Multiple dispatch can be added to Python using a library extension. For example, using the module multimethod.py and also with the module multimethods.py which provides CLOS-style multimethods for Python without changing the underlying syntax or keywords of the language.

None:\n \"\"\"Behavior when asteroid hits asteroid.\"\"\"\n # ...define new behavior...\n\ncollide.add_rule((Asteroid, Asteroid), aa_func)\n"}}'>fromtypingimport Any importgame_behaviors fromgame_objectsimport Asteroid, Spaceship frommultimethodsimport Dispatch collide: Dispatch = Dispatch() collide.add_rule((Asteroid, Spaceship), game_behaviors.as_func) collide.add_rule((Spaceship, Spaceship), game_behaviors.ss_func) collide.add_rule((Spaceship, Asteroid), game_behaviors.sa_func) defaa_func(a: Any, b: Any) -> None: """Behavior when asteroid hits asteroid.""" # ...define new behavior... collide.add_rule((Asteroid, Asteroid), aa_func)
fromplumimport dispatch @dispatch defcollide(a: Asteroid, b: Asteroid) -> None: """Behavior when asteroid hits a asteroid.""" # ...define new behavior... @dispatch defcollide(a: Asteroid, b: Spaceship) -> None: """Behavior when asteroid hits a spaceship.""" # ...define new behavior... # ...define further rules...

Emulating multiple dispatch

edit

C does not have dynamic dispatch, so it must be implemented manually in some form. Often an enum is used to identify the subtype of an object. Dynamic dispatch can be done by looking up this value in a function pointer branch table. Here is a simple example in C:

= %d\\n\", collide_with(a, a));\n printf(\"<a,s> = %d\\n\", collide_with(a, s));\n printf(\"<s,a> = %d\\n\", collide_with(s, a));\n printf(\"<s,s> = %d\\n\", collide_with(s, s));\n\n grelease(a);\n grelease(s);\n}\n"}}'>#include<stdio.h> #include<cos/Object.h> #include<cos/gen/object.h> // classes defclass(Asteroid) // data members endclass defclass(Spaceship) // data members endclass // generics defgeneric(bool,collide_with,_1,_2); // multimethods 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 // example of use intmain(void){ OBJa=gnew(Asteroid); OBJs=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++

edit

importstd; usingstd::unordered_map; classCollideable{ protected: explicitCollideable(uint32_tcid): tid{cid}{} virtual~Collideable()=default; constuint32_ttid;// type id usingCollisionHandler=void(Collideable::*)(Collideable&other); usingCollisionHandlers=unordered_map<uint64_t,CollisionHandler>; staticvoidaddHandler(uint32_tid1,uint32_tid2,CollisionHandlerhandler){ collisionCases.insert(CollisionHandlers::value_type(key(id1,id2),handler)); } staticuint64_tkey(uint32_tid1,uint32_tid2){ returnuint64_t(id1)<<32|id2; } staticinlineCollisionHandlerscollisionCases{}; public: voidcollideWith(Collideable&other){ if(autohandler=collisionCases.find(key(tid,other.tid));handler!=collisionCases.end()){ (this->*handler->second)(other);// pointer-to-method call }else{ // default collision handling } } }; classAsteroid:publicCollideable{ private: voidasteroidCollision(Collideable&other){ // handle Asteroid-Asteroid collision } voidspaceshipCollision(Collideable&other){ // handle Asteroid-Spaceship collision } public: Asteroid(): Collideable(cid){} ~Asteroid()=default; staticvoidinitCases(); staticinlineconstuint32_tcid=typeid(Asteroid).hash_code(); }; classSpaceship:publicCollideable{ private: voidasteroidCollision(Collideable&other){ // handle Spaceship-Asteroid collision } voidspaceshipCollision(Collideable&other){ // handle Spaceship-Spaceship collision } public: Spaceship(): Collideable(cid){} ~Spaceship()=default; staticvoidinitCases(); staticinlineconstuint32_tcid=typeid(Spaceship).hash_code();// class id }; voidAsteroid::initCases(){ addHandler(cid,cid,CollisionHandler(&Asteroid::asteroidCollision)); addHandler(cid,Spaceship::cid,CollisionHandler(&Asteroid::spaceshipCollision)); } voidSpaceship::initCases(){ addHandler(cid,Asteroid::cid,CollisionHandler(&Spaceship::asteroidCollision)); addHandler(cid,cid,CollisionHandler(&Spaceship::spaceshipCollision)); } intmain(intargc,char*argv[]){ Asteroid::initCases(); Spaceship::initCases(); Asteroida1; Asteroida2; Spaceships1; Spaceships2; a1.collideWith(a2); a1.collideWith(s1); s1.collideWith(s2); s1.collideWith(a1); }

The YOMM2 library provides a fast, orthogonal implementation of open multimethods.

The syntax for declaring open methods is inspired by a proposal for a native C++ implementation. The library requires that the user registers all the classes used as virtual arguments (and their sub-classes), but does not require any modifications to existing code. Methods are implemented as ordinary inline C++ functions; they can be overloaded and they can be passed by pointer. There is no limit on the number of virtual arguments, and they can be arbitrarily mixed with non-virtual arguments.

The library uses a combination of techniques (compressed dispatch tables, collision free integer hash table) to implement method calls in constant time, while mitigating memory usage. Dispatching a call to an open method with a single virtual argument takes only 15–30% more time than calling an ordinary virtual member function, when a modern optimizing compiler is used.

The Asteroids example can be implemented as follows:

\n\nimport std;\n\nusing std::unique_ptr;\n\nclass Collideable {\npublic:\n virtual ~Collideable() = default;\n};\n\nclass Asteroid : public Collideable {\n // ...\n};\n\nclass Spaceship : public Collideable {\n // ...\n};\n\nregister_classes(Collideable, Spaceship, Asteroid);\n\ndeclare_method(void, collideWith, (virtual_<Collideable&>, virtual_<Collideable&>));\n\ndefine_method(void, collideWith, (Collideable& left, Collideable& right)) {\n // default collision handling\n}\n\ndefine_method(void, collideWith, (Asteroid& left, Asteroid& right)) {\n // handle Asteroid-Asteroid collision\n}\n\ndefine_method(void, collideWith, (Asteroid& left, Spaceship& right)) {\n // handle Asteroid-Spaceship collision\n}\n\ndefine_method(void, collideWith, (Spaceship& left, Asteroid& right)) {\n // handle Spaceship-Asteroid collision\n}\n\ndefine_method(void, collideWith, (Spaceship& left, Spaceship& right)) {\n // handle Spaceship-Spaceship collision\n}\n\nint main(int argc, char* argv[]) {\n yorel::yomm2::update_methods();\n\n unique_ptr<Collideable> a1(std::make_unique<Asteroid>());\n unique_ptr<Collideable> a2(std::make_unique<Asteroid>());\n unique_ptr<Collideable> s1(std::make_unique<Spaceship>());\n unique_ptr<Collideable> s2(std::make_unique<Spaceship>());\n // note: types partially erased\n\n collideWith(*a1, *a2); // Asteroid-Asteroid collision\n collideWith(*a1, *s1); // Asteroid-Spaceship collision\n collideWith(*s1, *a1); // Spaceship-Asteroid collision\n collideWith(*s1, *s2); // Spaceship-Spaceship collision\n\n return 0;\n}\n"}}'>#include<yorel/yomm2/keywords.hpp> importstd; usingstd::unique_ptr; classCollideable{ public: virtual~Collideable()=default; }; classAsteroid:publicCollideable{ // ... }; classSpaceship:publicCollideable{ // ... }; register_classes(Collideable,Spaceship,Asteroid); declare_method(void,collideWith,(virtual_<Collideable&>,virtual_<Collideable&>)); define_method(void,collideWith,(Collideable&left,Collideable&right)){ // default collision handling } define_method(void,collideWith,(Asteroid&left,Asteroid&right)){ // handle Asteroid-Asteroid collision } define_method(void,collideWith,(Asteroid&left,Spaceship&right)){ // handle Asteroid-Spaceship collision } define_method(void,collideWith,(Spaceship&left,Asteroid&right)){ // handle Spaceship-Asteroid collision } define_method(void,collideWith,(Spaceship&left,Spaceship&right)){ // handle Spaceship-Spaceship collision } intmain(intargc,char*argv[]){ yorel::yomm2::update_methods(); unique_ptr<Collideable>a1(std::make_unique<Asteroid>()); unique_ptr<Collideable>a2(std::make_unique<Asteroid>()); unique_ptr<Collideable>s1(std::make_unique<Spaceship>()); unique_ptr<Collideable>s2(std::make_unique<Spaceship>()); // note: types partially erased collideWith(*a1,*a2);// Asteroid-Asteroid collision collideWith(*a1,*s1);// Asteroid-Spaceship collision collideWith(*s1,*a1);// Spaceship-Asteroid collision collideWith(*s1,*s2);// Spaceship-Spaceship collision return0; }

Stroustrup mentions in The Design and Evolution of C++ that he liked the concept of multimethods and considered implementing it in C++ but claims to have been unable to find an efficient sample implementation (comparable to virtual functions) and resolve some possible type ambiguity problems. He then states that although the feature would still be nice to have, that it can be approximately implemented using double dispatch or a type based lookup table as outlined in the C/C++ example above so is a low priority feature for future language revisions.

UML class Java single dispatch.svg

Muschevici, Radu; Potanin, Alex; Tempero, Ewan; Noble, James (2008). "Multiple dispatch in practice". Proceedings of the 23rd ACM SIGPLAN conference on Object-oriented programming systems languages and applications. OOPSLA '08. Nashville, TN, USA: ACM. pp. 563–582. doi:10.1145/1449764.1449808. ISBN 9781605582153. S2CID 7605233.
  • 1 2 3 4 5 Castagna, Giuseppe (1996). Object-Oriented Programming: A Unified Foundation. Progress in Theoretical Computer Science. Birkhäuser. p. 384. ISBN 978-0-8176-3905-1.
  • ↑ "Using type dynamic (C# Programming Guide)". Retrieved 2020-05-14.
  • ↑ Coady, Aric, multimethod: Multiple argument dispatching., retrieved 2021-01-28
  • ↑ multimethods.py Archived 2005-03-09 at the Wayback Machine, Multiple dispatch in Python with configurable dispatch resolution by David Mertz, et al.
  • ↑ "PyProtocols". Python Enterprise Application Kit. Retrieved 26 April 2019.
  • ↑ "Report on language support for Multi-Methods and Open-Methods for C ++" (PDF). 2007-03-11. Multiple dispatch – the selection of a function to be invoked based on the dynamic type of two or more arguments – is a solution to several classical problems in object-oriented programming.
  • ↑ yomm2, Fast, Orthogonal Open Multi-Methods for C++ by Jean-Louis Leroy.
  • ↑ "Multimethods in C# 4.0 With 'Dynamic'". Retrieved 2009-08-20.
  • ↑ Steele, Guy L. (1990). "28". Common LISP: The Language. Bedford, MA, U.S.A: Digital Press. ISBN 978-1-55558-041-4.
  • ↑ "Multimethods in Groovy". Retrieved 2008-04-13.
  • ↑ "Nim Manual: Multi-methods". Retrieved 2022-05-03.
  • ↑ "TADS 3 System Manual". Retrieved 2012-03-19.
  • ↑ "Notes for Programming Language Experts". Retrieved 2016-08-21.
  • ↑ "Dynamic multiple dispatch". docs.racket-lang.org. Retrieved 2018-03-12.

  • View original on Wikipedia | Back | FazBrowse Home