Dispatch múltiple, en ciència de la computació, és una característica d'alguns llenguatges de programació en els que una funció o mètode pot ser cridat en temps d'execució amb relació a una sèrie d'atributs o arguments. El dispatch múltiple és un multimètode o polimorfisme on la crida a la funció o mètode és servida dinàmicament depenent del tipus d'objecte.
Exemple En aquest exemple hi ha un mètode amb 4 formes que es cridaran en funció dels paràmetres que es passin :
Llenguatge Common Lisp (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 )
Perl 6 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 doesn't make 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));
Python from multimethods import Dispatch from game_objects import Asteroid, Spaceship from game_behaviors import ASFunc, SSFunc, SAFunc collide = Dispatch() collide.add_rule((Asteroid, Spaceship), ASFunc) collide.add_rule((Spaceship, Spaceship), SSFunc) collide.add_rule((Spaceship, Asteroid), SAFunc) def AAFunc(a, b): """Behavior when asteroid hits asteroid""" # ...define new behavior... collide.add_rule((Asteroid, Asteroid), AAFunc)
Suport en llenguatge de programació LLenguatges de programació que suporten multi dispatch : C# 4.0 Cecil Clojure Common Lisp (via the Common Lisp Object System) Dylan Elixir Fortress Groovy Haskell via multi-parameter type classes Julia Lasso Nice Nim Perl 6 R Scala,[citation needed] també via classes de tipus multiparàmetre Seed7 TADS Wolfram Language via symbolic pattern matching Xtend Multimètodes en altres llenguatges de programació mitjançant extensions : .NET (via la biblioteca MultiMethods.NET) C (via la biblioteca C Object System) C# (via la biblioteca multimethod-sharp) C++ (via la biblioteca yomm11 ) Factor (via l'estàndard multi-methods vocabulary) Java (usant l'extensió MultiJava) Perl (via el mòdule Class::Multimethods) Python (via PEAK-Rules, RuleDispatch, gnosis.magic.multimethods, PyMultimethods, or multipledispatch) Ruby (via la biblioteca The Multiple Dispatch Library and Multimethod Package and Vlx-Multimethods Package) Scheme (via ex: TinyCLOS) També, Haskell i Scala via classes de tipus multiparàmetre
Referències
Categoria:Programació