Dispatch múltiple
Aparença
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ó en 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.[1][2][3]
Exemple
[modifica]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
[modifica] (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
[modifica]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
[modifica]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ó
[modifica]- 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[Enllaç no actiu])
- C++ (via la biblioteca yomm11 Arxivat 2016-06-02 a Wayback Machine.)
- 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
[modifica]- ↑ «What's the difference between Polymorphism and Multiple Dispatch?» (en anglès). https://stackoverflow.com.+[Consulta: 24 maig 2017].
- ↑ «A polyglot's guide to multiple dispatch - Eli Bendersky's website» (en anglès). http://eli.thegreenplace.net.+[Consulta: 24 maig 2017].
- ↑ «Single, Dynamic, Multiple and Double Dispatching» (en anglès). http://isagoksu.com. Arxivat de l'original el 2017-05-22. [Consulta: 24 maig 2017].