Multimódszer

Az oldal jelenlegi verzióját még nem ellenőrizték tapasztalt közreműködők, és jelentősen eltérhet a 2015. január 5-én felülvizsgált verziótól ; az ellenőrzések 29 szerkesztést igényelnek .

A multimethod ( angolul  multimethod ) vagy a multiple dispatch ( angol  multiple dispatch ) egy olyan mechanizmus a programozási nyelvekben, amely lehetővé teszi, hogy a dinamikus típusoktól vagy argumentumértékektől függően több funkció közül válasszon egyet (például módszer túlterhelés egyes programozási nyelvekben). . Ez az egyszeri küldés ( virtuális függvények ) kiterjesztése, ahol a metódus kiválasztása dinamikusan történik az objektum tényleges típusa alapján, amelyen a metódust meghívták. A többszörös küldés általánosítja a dinamikus elküldést két vagy több objektum esetén.

A multimetódusokat kifejezetten támogatja a "Common Lisp Object System" ( CLOS ).

Feladás alapjai

A programfejlesztők hajlamosak a forráskódot elnevezett blokkokba csoportosítani, amelyeket hívásoknak, eljárásoknak, szubrutinoknak , függvényeknek vagy metódusoknak neveznek. Egy függvény kódja a meghívással kerül végrehajtásra, ami a nevével jelzett kódrészlet végrehajtásából áll. Ebben az esetben a vezérlés átmenetileg átkerül a hívott függvényre; amikor ez a funkció befejeződik, a vezérlés általában visszakerül a függvényhívást követő utasításhoz.

A funkcióneveket általában a céljuk leírására választják. Néha több funkciót is meg kell nevezni ugyanazon a néven, általában azért, mert fogalmilag hasonló feladatokat látnak el, de különböző típusú bemeneti adatokkal dolgoznak. Ilyen esetekben a függvény neve a hívás helyén nem elegendő a meghívandó kódblokk meghatározásához. A néven kívül ebben az esetben a hívott függvény argumentumainak száma és típusa is felhasználható a függvény konkrét megvalósításának kiválasztásához.

A hagyományosabb egyszeri küldés objektum-orientált programozási nyelvekben egy metódus meghívásakor (üzenet küldése Smalltalk -ban, tagfüggvény meghívása C++- ban ), az egyik argumentumát speciális módon kezelik, és meghatározzák, hogy a ( potenciálisan sok) ilyen nevű metódust kell meghívni. Sok nyelvben ezt a speciális argumentumot szintaktikailag jelzik, például számos programozási nyelvben metódus hívásakor egy speciális argumentum kerül a pont elé:

speciális módszer (egyéb, argumentumok, itt)

így a lion.sound() üvöltést és a veréb.hang() csipogást fog produkálni.

Ezzel szemben a többszörös kiküldéssel rendelkező nyelveken a kiválasztott metódus egyszerűen az a metódus, amelynek argumentumai megegyeznek a függvényhívás argumentumainak számával és típusával. Itt nincs olyan különleges érv, amely egy adott hívás által hivatkozott függvényt vagy metódust "tulajdonolja".

A Common Lisp Object System (CLOS) a többszörös küldés egyik első és jól ismert megvalósítása.

Adattípusok

Ha olyan nyelvekkel dolgozik, amelyeken a fordításkor adattípusok különböztethetők meg, a rendelkezésre álló funkcióopciók közötti választás fordításkor történhet. Az ilyen alternatív függvénybeállítások fordítási időben történő létrehozását általában függvénytúlterhelésnek nevezik .

Azokban a programozási nyelvekben, amelyek futásidőben határozzák meg az adattípusokat (késői kötés), a függvényopciók közötti választásnak futási időben kell megtörténnie a dinamikusan meghatározott függvény argumentumtípusok alapján. Azokat a függvényeket, amelyek alternatív megvalósítását ilyen módon választják ki, általában multimetódusoknak nevezik.

A függvényhívások dinamikus elküldésével kapcsolatos futási költségek is felmerülnek. Egyes nyelveken a függvénytúlterhelés és a multimetódusok közötti különbség elmosódhat, a fordító határozza meg, hogy a hívott függvény kiválasztása történhet-e fordítási időben, vagy futás közbeni lassabb diszpécserre van szükség.

Gyakorlati felhasználás

Annak felmérésére, hogy a gyakorlatban milyen gyakran alkalmaznak többszörös diszpécsert, Muschevici és munkatársai [1] dinamikus diszpécserezést használó alkalmazásokat vizsgáltak. Kilenc alkalmazást, többnyire fordítóprogramot elemeztek, hat különböző programozási nyelven: Common Lisp Object System , Dylan , Cecil, MultiJava, Diesel és Nice. Az eredmények azt mutatják, hogy az általános függvények 13–32%-a használ egyargumentumos dinamikus gépelést, míg a függvények 2,7–6,5%-a több argumentumú dinamikus gépelést. Az általános függvények fennmaradó 65–93%-a egy meghatározott metódussal rendelkezik (túlterhelt), ezért nem vették figyelembe argumentumaik dinamikus típusát. Ezenkívül a tanulmány arról számol be, hogy az általános funkciók 2–20%-ának kettő, 3–6%-ának pedig három konkrét megvalósítása volt. A nagyszámú konkrét megvalósítással rendelkező funkciók aránya rohamosan csökkent.

Elmélet

A többhívásos nyelvek elméletét először Castagna és munkatársai dolgozták ki, a túlterhelt, késői kötéssel rendelkező függvények modelljének meghatározásával [2] [3] . Ez adta az első formalizálást az objektum-orientált programozási nyelvek kovariancia és kontravariációjának [4] problémájának, valamint a bináris módszerek [5] problémájának megoldását .

Példa

A multimetódusok és az egyszeri feladás közötti különbség jobb megértése érdekében a következő példa bemutatható. Képzelj el egy játékot, amelyben számos egyéb tárgy mellett kisbolygók és űrhajók is vannak. Ha bármely két objektum ütközik, a programnak ki kell választania egy bizonyos műveleti algoritmust, attól függően, hogy mi ütközött mivel.

Common Lisp

Egy több módszert alkalmazó nyelvben, mint például a Common Lisp , a kód így néz ki:

( defgenerikus ütközés ( x y )) ( defmethod ütközés (( x aszteroida ) ( y aszteroida )) ;; aszteroida ütközik aszteroidával ) ( defmethod ütközik (( x aszteroida ) ( y űrhajó )) ;;aszteroida ütközik űrhajóval ) ( defmethod ütközik (( x űrhajó ) ( y aszteroida )) ;;űrhajó ütközik egy aszteroidával ) ( defmethod ütközik (( x űrhajó ) ( y űrhajó )) ;;űrhajó ütközik űrhajóval )

és hasonlóan más módszerekhez. Az explicit ellenőrzés és a „dinamikus öntés” itt nem használatos. 

A többszörös kiküldéssel a metódusok osztályokban történő meghatározásának és objektumokban való tárolásának hagyományos megközelítése kevésbé vonzóvá válik, mivel minden ütközési módszer egy helyett két különböző osztályra hivatkozik. Így a metódushívás speciális szintaxisa általában eltűnik, így a metódushívás pontosan úgy néz ki, mint egy normál függvényhívás, és a metódusok nem osztályok szerint, hanem általános függvényekbe vannak csoportosítva .

Raku

A Raku a korábbi verziókhoz hasonlóan más nyelvekből és típusrendszerekből származó bevált ötleteket használ, hogy lenyűgöző előnyöket kínáljon a fordítóoldali kódelemzésben és hatékony szemantikában a többszörös kiküldés révén.

Multimetódusokkal és multisubrutinokkal is rendelkezik. Mivel a legtöbb utasítás szubrutin, vannak többszörös kiküldéssel rendelkező utasítások is.

A szokásos típusmegszorítások mellett "hol" típusú megszorításokkal is rendelkezik, ami lehetővé teszi nagyon speciális szubrutinok létrehozását.

részhalmaz Valós tömeg ahol 0 ^ .. ^ Inf ; role Stellar-Object { has Mass $ .mass szükséges ; metódusnév () visszaadja Str { ...}; } osztályú aszteroida Csillagobjektum { metódus neve ( ) { 'aszteroida' } } class Űrhajó csinál Stellar-Object { has Str $.name = 'valami névtelen űrhajó' ; } my Str @ megsemmisült = < eltüntetett megsemmisült mangled >; my Str @ sérült = "  sérült 'ütközött a következővel: 'sérült:'  "; # Több jelöltet adunk a numerikus összehasonlító operátorokhoz, mert numerikusan hasonlítjuk össze őket, # de nincs értelme, hogy az objektumokat numerikus típusra kényszerítsük. # (Ha kényszerítenének, akkor nem feltétlenül kellene hozzáadnunk ezeket az operátorokat. ) # Ugyanígy teljesen új operátorokat is definiálhattunk volna. több al - infix: " <=> " ( Csillag-objektum:D $a , Csillag-objektum:D $b ) { $a . tömeg <=> $b . tömeg } multi sub infix: " < " ( Csillag-objektum:D $a , Csillag-objektum:D $b ) { $a . tömeg < $b . tömeg } multi sub infix: " > " ( Csillag-objektum:D $a , Csillag-objektum:D $b ) { $a . tömeg > $b . tömeg } multi sub infix: " == " ( Csillag-objektum:D $a , Csillag-objektum:D $b ) { $a . tömeg == $b . tömeg } # Határozzon meg egy új több diszpécsert, és adjon hozzá néhány típusmegkötést a paraméterekhez. # Ha nem definiáljuk, akkor kaptunk volna egy általánost, amely nem tartalmaz megkötéseket. proto sub ütközés ( Csillag-objektum:D $, Csillag-objektum:D $ ) {*} # Itt nem kell megismételni a típusokat, mivel ugyanazok, mint a prototípus. # A 'hol' megkötés technikailag csak a $b-re vonatkozik, nem a teljes aláírásra. # Vegye figyelembe, hogy a „hol” megszorítás a korábban hozzáadott „<” operátorjelöltet használja. multi sub collide ( $a , $b ahol $a < $b ) { mondd: "$a.name() was @destroyed.pick() by $b.name()" ; } multi sub collide ( $a , $b ahol $a > $b ) { # újraküldés az előző jelöltnek, az argumentumok felcserélve a következővel: $b , $a ; } # Ennek az első kettő után kell lennie, mert a többinél # 'hol' megszorítások vannak, amelyek a # feliratok megírásának sorrendjében kerülnek ellenőrzésre. (Ez mindig egyezne. ) multi sub collide ( $a , $b ){ # véletlenszerű sorrendbe állítás my ( $n1 , $n2 ) = ( $a . név , $b . név ). pick (*); mondd: "$n1 @damaged.pick() $n2" ; } # A következő két jelölt bárhol lehet a proto után, # mert speciálisabb típusaik vannak, mint az előző háromnak. # Ha a hajók tömege nem egyenlő, az első két jelölt közül az egyiket hívják. több rész ütközik ( $a űrhajó , $b űrhajó ahol $a == $b ){ my ( $n1 , $n2 ) = ( $a . név , $b . név ). pick (*); mondd: "$n1 ütközött $n2-vel, és mindkét hajó volt" , ( @detroyed . pick , 'bal sérült' ). csákány ; } # Az attribútumokat az aláíráson belül változókba csomagolhatja. # Akár egy megkötés is lehet rájuk `(:mass($a) ahol 10)`. többszörös összeütközések ( $ aszteroida (: tömeg ( $a )), aszteroida $ (: tömeg ( $b )) ){ mondjuk "két aszteroida ütközött és egy nagyobb { $a + $b } tömegű aszteroidává egyesült" ; } my Spaceship $Enterprise .= new (: tömeg ( 1 ),: név ( 'The Enterprise' )); ütközik aszteroida . új (: tömeg ( .1 )), $Enterprise ; ütközik $Enterprise , Űrhajó . új (: tömeg ( .1 )); ütközik $Enterprise , Aszteroida . új (: tömeg ( 1 )); ütközik $Enterprise , Űrhajó . új (: tömeg ( 1 )); ütközik aszteroida . új (: tömeg ( 10 )), Kisbolygó . új (: tömeg ( 5 ));

Python

Azokon a nyelveken, amelyek szintaktikai szinten nem támogatják a többszörös elküldést, mint például a Python , általában lehetséges a többszörös küldés használata bővítménykönyvtárak használatával. Például a multimethods.py modul [6] a szintaxis vagy a nyelvi kulcsszavak megváltoztatása nélkül valósítja meg a CLOS-stílusú multimetódusokat Pythonban .

multimethods importból Feladás game_objects -ből import Aszteroida , Űrhajó a game_behaviors - ból import ASFunc , SSFunc , SAFunc ütközik = Dispatch () ütközik . add_rule (( Aszteroida , Űrhajó ), ASFunc ) ütközik . add_rule (( Űrhajó , Űrhajó ), SSFunc ) ütközik . add_rule (( Űrhajó , Aszteroida ), SAFunc ) def AAFunc ( a , b ): """ Viselkedés kisbolygó becsapódásakor""" # ...új viselkedés meghatározása... ütközés . add_rule (( Aszteroida , Kisbolygó ), AAFunc ) # ...később... ütközik ( 1. dolog , 2. dolog )

Funkcionálisan nagyon hasonlít a CLOS példához, de a szintaxis a szabványos Python szintaxist követi.

A Python 2.4 dekorátorok használatával Guido van Rossum írt egy példa implementációt a multimetódusokra [7] egyszerűsített szintaxissal:

@multimethod ( Asteroid , Asteroid ) def collide ( a , b ): """ Viselkedés, amikor aszteroida becsapódik aszteroidába""" # ...új viselkedés meghatározása... @multimethod ( Aszteroida , Űrhajó ) def ütközés ( a , b ) : """Viselkedés, amikor aszteroida becsapódik az űrhajóba""" # ...új viselkedés meghatározása... # ... egyéb többmódszeres szabályok meghatározása ...

majd definiáljuk a dekorátor multimetódusát.

A PEAK-Rules csomag a többszörös küldést valósítja meg a fenti példához hasonló szintaxissal. [nyolc]

Többszörös küldés emuláció

Java

Azokon a nyelveken, amelyeknek csak egyetlen küldése van, mint például a Java , ez a kód így néz ki ( a látogatói minta azonban segíthet megoldani ezt a problémát):

/* Példa a futásidejű típusok összehasonlítására a Java "instanceof" operátorán keresztül */ interface Collideable { /* Ennek osztályozása nem változtatja meg a bemutatót. */ void collideWith ( Collideable other ); } osztály Aszteroida implements Collideable { public void collideWith ( Collideable other ) { if ( other instanceof Asteroid ) { // Aszteroida-Aszteroida ütközés kezelése. } else if ( űrhajó másik példánya ) { // Aszteroida-űrhajó ütközés kezelése. } } } osztályú Űrhajó implementációk Ütközhető { public void collideWith ( Collideable other ) { if ( other instance of Asteroid ) { // Űrhajó-Aszteroida ütközés kezelése. } else if ( other instanceof Spaceship ) { // Űrhajó-űrhajó ütközés kezelése. } } }

C

A C-nek nincs dinamikus elküldése, ezért valamilyen formában kézzel kell megvalósítani. A felsorolást gyakran használják egy objektum altípusának azonosítására. A dinamikus küldés úgy valósítható meg, hogy ezt az értéket a függvénymutatók elágazási táblázatában keresi meg. Íme egy egyszerű példa C-ben:

typedef void ( * CollisionCase )(); void collision_AA () { /* Aszteroida-Aszteroida ütközés kezelése */ }; void collision_AS () { /* Kisbolygó-hajó ütközésfeldolgozás */ }; void collision_SA () { /* Hajó-Aszteroida ütközéskezelés */ }; void collision_SS () { /* hajók közötti ütközések kezelése */ }; typedef enum { aszteroida = 0_ _ űrhajó , A num_thing_types /* nem egy objektumtípus, az objektumok számának meghatározására szolgál */ } Thing ; CollisionCase collisionCases [ num_thing_types ][ num_thing_types ] = { { & collision_AA , & collision_AS }, { & collision_SA , & collision_SS } }; void ütközés ( Thing a , Thing b ) { ( * collisionCases [ a ][ b ])(); } int main () { ütközik ( űrhajó , aszteroida ); }

C++

2015-től a C++ csak az egyszeri küldést támogatja, bár a többszörös küldés támogatása is mérlegelés alatt áll. [9]  Ennek a korlátozásnak a megkerülő megoldásai hasonlóak: vagy a látogatói minta vagy a dinamikus casting használatával:

// Példa a futásidejű típusok összehasonlítására a dynamic_cast segítségével struct Thing { virtuális üreg ütközik ( Dolog és egyéb ) = 0 ; }; struct Aszteroida : Thing { void collideWith ( dolog és egyéb ) { // A dynamic_cast egy mutatótípushoz NULL értéket ad vissza, ha az átküldés meghiúsul // (a dynamic_cast egy referenciatípusra kivételt jelentene hiba esetén) if ( Asteroid * asteroid = dynamic_cast < Asteroid *> ( & other )) { // Aszteroida-Aszteroida ütközés kezelése } else if ( Űrhajó * űrhajó = dynamic_cast < Űrhajó *> ( és egyéb )) { // aszteroida-űrhajó ütközés kezelése } else { // alapértelmezett ütközéskezelés itt } } }; struct Űrhajó : Thing { void collideWith ( dolog és egyéb ) { if ( Aszteroida * aszteroida = dynamic_cast < Asteroid *> ( és egyéb )) { // Űrhajó-Aszteroida ütközés kezelése } else if ( Űrhajó * űrhajó = dynamic_cast < Űrhajó *> ( és egyéb )) { // Űrhajó-űrhajó ütközés kezelése } else { // alapértelmezett ütközéskezelés itt } } };

vagy keresési táblázatok a metódusokra mutató mutatókhoz:

#include <typeinfo> #include <rendezetlen_térkép> typedef unsigned uint4 ; typedef unsigned long long uint8 ; class Thing { védett : Thing ( const uint4 cid ) : tid ( cid ) {} const uint4 tid ; // írja be az id typedef void ( Thing ::* CollisionHandler )( Thing & other ); typedef std :: unordered_map < uint8 , CollisionHandler > CollisionHandlerMap ; static void addHandler ( const uint4 id1 , const uint4 id2 , const CollisionHandler kezelő ) { ütközésCases . insert ( CollisionHandlerMap :: érték_típus ( kulcs ( id1 , id2 ), kezelő )); } statikus uint8 kulcs ( const uint4 id1 , const uint4 id2 ) { return uint8 ( id1 ) << 32 | id2 ; } static CollisionHandlerMap collisionCases ; nyilvános : void collideWith ( dolog és egyéb ) { CollisionHandlerMap :: const_iterator handler = collisionCases . talál ( kulcs ( tid , egyéb . tid )); if ( kezelő != ütközésCases . end ()) { ( ez ->* kezelő -> második )( egyéb ); // pointer-to-method call } else { // alapértelmezett ütközéskezelés } } }; osztály aszteroida : nyilvános dolog { void asteroid_collision ( Thing és egyéb ) { /*aszteroida-aszteroida ütközés kezelése*/ } void spaceship_collision ( Thing és egyéb ) { /*aszteroida-űrhajó ütközés kezelése*/ } nyilvános : Kisbolygó ( ) : Dolog ( cid ) {} static void initCases (); statikus const uint4 cid ; }; osztály űrhajó : public Thing { void asteroid_collision ( Thing & other ) { /*handle Spaceship-Asteroid collision*/ } void spaceship_collision ( Thing & other ) { /*handle Spaceship-Spaceship collision*/ } nyilvános : Űrhajó () : Dolog ( cid ) {} static void initCases (); statikus const uint4 cid ; // osztályazonosító }; Thing :: CollisionHandlerMap Thing :: collisionCases ; const uint4 Aszteroida :: cid = typeid ( Aszteroida ). hash_code (); const uint4 Űrhajó :: cid = typeid ( Űrhajó ). hash_code (); void Asteroid::initCases () { addHandler ( cid , cid , ( CollisionHandler ) & Asteroid :: asteroid_collision ); addHandler ( cid , Spaceship :: cid , ( CollisionHandler ) & Asteroid :: spaceship_collision ); } void Űrhajó::initCases () { addHandler ( cid , Aszteroida :: cid , ( CollisionHandler ) & Spaceship :: asteroid_collision ); addHandler ( cid , cid , ( CollisionHandler ) & Spaceship :: spaceship_collision ); } int main () { Aszteroida :: initCases (); űrhajó :: initCases (); a1 , a2 aszteroida ; űrhajó s1 , s2 ; a1 . ütközik ( a2 ); a1 . ütközik ( s1 ); s1 . ütközik ( s2 ); s1 . ütközik ( a1 ); }

A yomm11 könyvtár [10] lehetővé teszi ennek a megközelítésnek az automatizálását.

A The Design and Evolution of C++ című könyvében Stroustrup megemlíti, hogy szereti a multimetódusok koncepcióját, és fontolóra vette ezek C++-ban való megvalósítását, de azt állítja, hogy nem talált példát hatékony (a virtuális függvényekkel összehasonlítva) megvalósítására. és megoldani néhány lehetséges típusú kétértelműségi problémát. Amellett érvel továbbá, hogy bár jó lenne megvalósítani ennek a koncepciónak a támogatását, a fenti C/C++ példában leírtak szerint kettős küldéssel vagy típusalapú keresőtáblázattal közelíthető, így ez a feladat alacsony prioritású a fejlesztésben. a nyelv jövőbeli verzióiról. [tizenegy]

Megvalósítás programozási nyelveken

Multimetódusok támogatása más nyelveken kiterjesztéseken keresztül:

A Haskell és a Scala többparaméteres típusú osztályai  több metódus emulálására is használhatók.

Jegyzetek

  1. Muschevici, Radu; Potanin, Alex; Tempero, Ewan; Noble, James (2008). "Többszörös kiszállítás a gyakorlatban" . A 23. ACM SIGPLAN konferencia anyaga az objektum-orientált programozási rendszerek nyelveiről és alkalmazásairól . OOPSLA '08 (Nashville, TN, USA: ACM): 563–582
  2. Giuseppe Castagna; Giorgio Ghelli és Giuseppe Longo (1995). "Túlterhelt függvények kalkulusa altípusozással." Archiválva : 2018. november 18. a Wayback Machine -nál . Információ és számítás  (Akadémiai sajtó)  117  (1): 115–135
  3. Castagna, Giuseppe (1996). Objektum-orientált programozás: Egységes Alapítvány . Birkhauser. p. 384.
  4. Giuseppe Castagna (1995). "Kovariancia és kontravariancia: konfliktus ok nélkül" Archivált : 2018. november 20., a Wayback Machine webhelyen . Tranzakciók programozási nyelvekkel és rendszerekkel (TOPLAS)  (ACM)  17  (3). doi : 10.1145/203095.203096
  5. Kim Bruce; Luca Cardelli; Giuseppe Castagna; Gary T. Leavens; Benjamin Pierce (1995). "A bináris módszerekről" archiválva : 2018. november 19. a Wayback Machine -nál . Az objektumrendszerek elmélete és gyakorlata  1  (3)
  6. multimethods.py Archiválva : 2005. március 9. a Wayback Machine -nél , Többszörös küldés Pythonban konfigurálható küldési felbontással, David Mertz et al.
  7. Ötperces multimetódusok Pythonban . Letöltve: 2016. július 16. Az eredetiből archiválva : 2021. május 29.
  8. "PEAK-Rules 0.5a1.dev" archiválva : 2017. március 14. a Wayback Machine -nél . Python csomagindex . Letöltve: 2014. március 21.
  9. Archivált másolat . Letöltve: 2016. július 16. Az eredetiből archiválva : 2016. március 17.
  10. yomm11 archiválva : 2016. június 2., a Wayback Machine , Open Multi-Methods for C++11, Jean-Louis Leroy.
  11. Stroustrup, Bjarne (1994). 13.8. szakasz. A C++ tervezése és fejlődése . Indianapolis, IN, USA: Addison Wesley. ISBN  0-201-54330-3 .
  12. Steele, Guy L. (1990). 28. fejezet. Common LISP: The Language Archivált : 2017. december 17. a Wayback Machine -nél . Bedford, MA, USA: Digital Press. ISBN  1-55558-041-6 .
  13. „Típusórák: a tervezési tér felfedezése” Archiválva : 2016. augusztus 12. a Wayback Machine -nál . 1997-05-02.
  14. "Elixir Lang | Kezdő lépések | Modulok" Archiválva : 2016. július 20. a Wayback Machine -nél . Letöltve2016-02-21.
  15. "Háttér és célok" archiválva 2020. április 4-én a Wayback Machine -nél . Letöltve: 2008-04-13.
  16. "Visitor Pattern versus Multimethods" archiválva 2021. február 5-én a Wayback Machine -nél . Letöltve 2008-04-13.
  17. "Cecil Language" archiválva : 2016. szeptember 1. a Wayback Machine -nél . Letöltve: 2008-04-13.
  18. „Hogyan működnek az S4-módszerek” archiválva : 2021. május 10. a Wayback Machine -en  (PDF). Letöltve: 2008-04-13.
  19. "Módszerek" archiválva : 2016. július 17. a Wayback Machine -nél . A Julia kézikönyv . Julialang. Letöltve: 2014. május 11.
  20. "Multimethods in Groovy" Archiválva : 2011. augusztus 12. a Wayback Machine -nél . Letöltve: 2008-04-13.
  21. „Módszerek – LassoGuide 9.2” archiválva : 2021. június 13. a Wayback Machine -nél . Letöltve: 2014-11-11.
  22. "Perl 6 FAQ" Archiválva : 2012. március 13. a Wayback Machine -nél . Letöltve: 2008-04-13.
  23. „Multiple Dispatch in Seed7” archiválva 2021. január 29-én a Wayback Machine -nél . Letöltve: 2011-04-23
  24. "Multimethods in Clojure" Archiválva : 2015. szeptember 20. a Wayback Machine -nál . Letöltve: 2008-09-04.
  25. "Multimethods in C# 4.0 With 'Dynamic" Archiválva : 2009. augusztus 25. a Wayback Machine -nél . Letöltve 2009-08-20.
  26. "The Fortress Language Specification, Version 1.0" Archiválva : 2013. január 20. a Wayback Machine -nél (PDF). Letöltve: 2010-04-23.
  27. "TADS 3 rendszerkézikönyv" archiválva 2017. február 14-én a Wayback Machine -nál . Letöltve: 2012-03-19
  28. "Többszörös feladás" Archivált : 2016. július 15. a Wayback Machine -nél .
  29. "Nim Manual" archiválva : 2017. szeptember 24. a Wayback Machine -nél . Letöltve: 2015-05-08.