- Множественная диспетчеризация
-
Мультиме́тод (англ. multimethod) или мно́жественная диспетчериза́ция (англ. multiple dispatch) — это механизм, позволяющий выбрать одну из нескольких функций в зависимости от динамических типов аргументов. Таким образом, в отличие от обычных виртуальных функций выбор осуществляется с учётом не одного типа объекта, а нескольких. А в отличие от статической перегрузки функций выбор осуществляется на основе информации о динамических типах аргументов.
В явном виде мультиметоды поддерживаются сопоставления с образцом (pattern matching).
Является обобщением понятий виртуальной функции и статической перегрузки функций.
Содержание
Примеры
C++
/* Example using run time type comparison */ void Asteroid::collide_with(Thing * other) { Asteroid * other_asteroid = dynamic_cast<Asteroid*>(other); if (other_asteroid) { // deal with asteroid hitting asteroid return; } Spaceship * other_spaceship = dynamic_cast<Spaceship*>(other); if (other_spaceship) { // deal with asteroid hitting spaceship return; } } void Spaceship::collide_with(Thing * other) { Asteroid * other_asteroid = dynamic_cast<Asteroid*>(other); if (other_asteroid) { // deal with spaceship hitting asteroid return; } Spaceship * other_spaceship = dynamic_cast<Spaceship*>(other); if (other_spaceship) { // deal with spaceship hitting spaceship return; } }
или:
/* Example using polymorphism and method overloading */ void Asteroid::collide_with(Thing * other) { other->collide_with(this); } void Asteroid::collide_with(Asteroid * other) { // deal with asteroid hitting asteroid } void Asteroid::collide_with(Spaceship * other) { // deal with asteroid hitting spaceship } void Spaceship::collide_with(Thing * other) { other->collide_with(this); } void Spaceship::collide_with(Spaceship * other) { // deal with spaceship hitting spaceship } void Spaceship::collide_with(Asteroid * other) { // deal with spaceship hitting asteroid }
Python
С помощью модуля multimethods.py (из Gnosis Utils):
from multimethods import Dispatch class Asteroid(object): pass class Spaceship(object): pass def asteroid_with_spaceship(a1, s1): print "A-><-S" def asteroid_with_asteroid(a1, a2): print "A-><-A" def spaceship_with_spaceship(s1, s2): print "S-><-S" collide = Dispatch() collide.add_rule((Asteroid, Spaceship), asteroid_with_spaceship) collide.add_rule((Asteroid, Asteroid), asteroid_with_asteroid) collide.add_rule((Spaceship, Spaceship), spaceship_with_spaceship) collide.add_rule((Spaceship, Asteroid), lambda x,y: asteroid_with_spaceship(y,x)) a, s1, s2 = Asteroid(), Spaceship(), Spaceship() collision1 = collide(a, s1)[0] collision2 = collide(s1, s2)[0]
Ruby
С помощью модуля Vlx-multi:
require 'vlx_multi' class Asteroid end class Spaceship end vlxm(:collide, Asteroid, Asteroid) do |_1,_2| puts 'A-><-A' end vlxm(:collide, Asteroid, Spaceship) do |_1,_2| puts 'A-><-S' end vlxm(:collide, Spaceship, Asteroid ) do |_1,_2| puts 'S-><-A' end vlxm(:collide, Spaceship, Spaceship ) do |_1,_2| puts 'S-><-S' end s = Spaceship.new a = Asteroid.new collide(a,s) collide(s,s) collide(s,a) collide(a,a)
Ссылки
- Клюев, Александр Мультиметоды и С++. RSDN Magazine #2-2003 (19 июля 2003). Проверено 11 июня 2006.
- Эволюция мультиметодов при процедурном подходе
Wikimedia Foundation. 2010.