Топ питань
Часова шкала
Чат
Перспективи

Мультиметод

З Вікіпедії, вільної енциклопедії

Remove ads

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

В явному вигляді мультиметоди підтримуються «об'єктною системою типів Common Lisp’а» (CLOS).

Remove ads

Приклад

Узагальнити
Перспектива

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

В мові з підтримкою мультиметодів, такій, як 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))
  ;;космічний корабель зіштовхується з космічним кораблем
  )


Приклад реалізації на мові С#
namespace MultipleDispatch
{
	enum Outcome
	{
		Win,
		Lose,
		Draw,
	}

	abstract class Item
	{
		public abstract Outcome Compete(Item item);

		public abstract Outcome Evaluate(Paper paper);
		public abstract Outcome Evaluate(Scissors scissors);
		public abstract Outcome Evaluate(Rock rock);
	}

	class Paper : Item
	{
		public override Outcome Compete(Item item) => item.Evaluate(this);

		public override Outcome Evaluate(Paper paper) => Outcome.Draw;
		public override Outcome Evaluate(Scissors scissors) => Outcome.Win;
		public override Outcome Evaluate(Rock rock) => Outcome.Lose;
	}

	class Scissors : Item
	{
		public override Outcome Compete(Item item) => item.Evaluate(this);

		public override Outcome Evaluate(Paper paper) => Outcome.Lose;
		public override Outcome Evaluate(Scissors scissors) => Outcome.Draw;
		public override Outcome Evaluate(Rock rock) => Outcome.Win;
	}

	class Rock : Item
	{
		public override Outcome Compete(Item item) => item.Evaluate(this);

		public override Outcome Evaluate(Paper paper) => Outcome.Win;
		public override Outcome Evaluate(Scissors scissors) => Outcome.Lose;
		public override Outcome Evaluate(Rock rock) => Outcome.Draw;
	}

	class Program
	{
		static Item GetRandomItem()
		{
			switch (new System.Random().Next(3))
			{
				case 0: return new Paper();
				case 1: return new Scissors();
				case 2: return new Rock();

				default: throw new System.InvalidOperationException("Wrong item type");
			}
		}

		static void Main(string[] args)
		{
			Item item1 = GetRandomItem();
			Item item2 = GetRandomItem();

			System.Console.WriteLine($"{item1.GetType().Name} - {item1.Compete(item2)} - {item2.GetType().Name}");
		}
	}
}
Приклад реалізації на мові С# (із використанням dynamic)
namespace MultipleDispatchPattern
{
	enum Outcome
	{
		Win,
		Lose,
		Draw,
	}

	abstract class Item
	{
		public Outcome Compete(Item item) => Evaluate(this as dynamic, item as dynamic);

		private static Outcome Evaluate(Paper paper1, Paper paper2) => Outcome.Draw;
		private static Outcome Evaluate(Paper paper, Scissors scissors) => Outcome.Lose;
		private static Outcome Evaluate(Paper paper, Rock rock) => Outcome.Win;
		private static Outcome Evaluate(Scissors scissors, Paper paper) => Outcome.Win;
		private static Outcome Evaluate(Scissors scissors1, Scissors scissors2) => Outcome.Draw;
		private static Outcome Evaluate(Scissors scissors, Rock rock) => Outcome.Lose;
		private static Outcome Evaluate(Rock rock, Paper paper) => Outcome.Lose;
		private static Outcome Evaluate(Rock rock, Scissors scissors) => Outcome.Win;
		private static Outcome Evaluate(Rock rock1, Rock rock2) => Outcome.Draw;
	}

	class Paper : Item
	{
	}

	class Scissors : Item
	{
	}

	class Rock : Item
	{
	}

	class Program
	{
		static Item GetRandomItem()
		{
			switch (new System.Random().Next(3))
			{
				case 0: return new Paper();
				case 1: return new Scissors();
				case 2: return new Rock();

				default: throw new System.InvalidOperationException("Wrong item type");
			}
		}

		static void Main(string[] args)
		{
			Item item1 = GetRandomItem();
			Item item2 = GetRandomItem();

			System.Console.WriteLine($"{item1.GetType().Name} - {item1.Compete(item2)} - {item2.GetType().Name}");
		}
	}
}
Remove ads

Посилання

  • Bjarne Stroustrup; Yuriy Solodkyy; Peter Pirkelbauer (2007). Open Multi-Methods for C++ (PDF). ACM 6th International Conference on Generative Programming and Component Engineering. Архів оригіналу (PDF) за 29 квітня 2021. Процитовано 2 серпня 2015.
Remove ads
Loading related searches...

Wikiwand - on

Seamless Wikipedia browsing. On steroids.

Remove ads