Мультиметод

Материал из Википедии — свободной энциклопедии
Перейти к: навигация, поиск

Мультиме́тод (англ. multimethod) или мно́жественная диспетчериза́ция (англ. multiple dispatch) — механизм, позволяющий выбрать одну из нескольких функций в зависимости от динамических типов или значений аргументов. Представляет собой расширение одиночной диспетчеризации (виртуальных функций), где выбор метода осуществляется динамически на основе фактического типа объекта. Множественная диспетчеризация обобщает динамическую диспетчеризацию для случаев с двумя или более объектами.

В явном виде мультиметоды поддерживаются «объектной системой Common Lisp’а» (CLOS).

Пример[править | править исходный текст]

Для лучшего понимания разницы между мультиметодами и одиночной диспетчеризацией можно продемонстрировать следующий пример. Представим себе игру, в которой, наряду с разнообразными другими объектами, присутствуют астероиды и космические корабли. Когда два каких-либо объекта сталкиваются, программа должна выбрать какой-либо определенный алгоритм действий, в зависимости от того, что столкнулось с чем.

В языке с поддержкой мультиметодов, таком, как Common Lisp, код выглядел бы вот так:

(defgeneric collide (x y))
 
(defmethod collide ((x asteroid) (y asteroid))
  ;;астероид сталкивается с астероидом
  )
 
(defmethod collide ((x asteroid) (y spaceship))
  ;;астероид сталкивается с космическим кораблем
  )
 
(defmethod collide ((x spaceship) (y asteroid))
  ;;космический корабль сталкивается с астероидом
  )
 
(defmethod collide ((x spaceship) (y spaceship))
  ;;космический корабль сталкивается с космическим кораблем
  )

Реализация на C# 4.0, с использованием dynamic типов:

class Program
{
  class Thing { }
  class Asteroid : Thing { }
  class Spaceship : Thing { }
 
  static void CollideWithImpl(Asteroid x, Asteroid y) 
  {
    // астероид сталкивается с астероидом
  }
 
  static void CollideWithImpl(Asteroid x, Spaceship y) 
  {
    // астероид сталкивается с космическим кораблем
  }
 
  static void CollideWithImpl(Spaceship x, Asteroid y) 
  {
    // космический корабль сталкивается с астероидом
  }
 
  static void CollideWithImpl(Spaceship x, Spaceship y) 
  {
    // космический корабль сталкивается с космическим кораблем
  }
 
  static void CollideWith(Thing x, Thing y)
  {
    dynamic a = x;
    dynamic b = y;
    CollideWithImpl(a, b);
  }
 
  static void Main(string[] args)
  {
    var asteroid = new Asteroid();
    var spaceship = new Spaceship();
    CollideWith(asteroid, spaceship);
    CollideWith(spaceship, spaceship);
  }
}

В данном случае, естественно, следует отличать мультиметоды от статической перегрузки, так как, в отличие от последней, диспетчеризация происходит в рантайме.