В чем разница между полиморфизмом и множественной отправкой?
... или это одно и то же? Я заметил, что у каждого есть своя собственная запись в Википедии: Полиморфизм, Многократная рассылка, но у меня возникают проблемы с различием понятий.
Изменить: И как перегрузка вписывается во все это?
7 ответов
Полиморфизм - это средство, которое позволяет языку / программе принимать решения во время выполнения, какой метод вызывать, основываясь на типах параметров, отправляемых этому методу.
Количество параметров, используемых языком / средой выполнения, определяет "тип" полиморфизма, поддерживаемого языком.
Одиночная отправка - это тип полиморфизма, когда используется только один параметр (получатель сообщения - this
, или же self
) определить звонок.
Множественная диспетчеризация - это тип полиморфизма, когда в определении параметров для вызова метода используются несколько параметров. В этом случае приемник, а также типы параметров метода используются, чтобы указать, какой метод вызывать.
Таким образом, вы можете сказать, что полиморфизм - это общий термин, а множественная и единичная отправка - это конкретные типы полиморфизма.
Приложение: Перегрузка происходит во время компиляции. Он использует информацию о типе, доступную во время компиляции, чтобы определить, какой тип метода вызывать. Одиночная / множественная отправка происходит во время выполнения.
Образец кода:
using NUnit.Framework;
namespace SanityCheck.UnitTests.Stackru
{
[TestFixture]
public class DispatchTypes
{
[Test]
public void Polymorphism()
{
Baz baz = new Baz();
Foo foo = new Foo();
// overloading - parameter type is known during compile time
Assert.AreEqual("zap object", baz.Zap("hello"));
Assert.AreEqual("zap foo", baz.Zap(foo));
// virtual call - single dispatch. Baz is used.
Zapper zapper = baz;
Assert.AreEqual("zap object", zapper.Zap("hello"));
Assert.AreEqual("zap foo", zapper.Zap(foo));
// C# has doesn't support multiple dispatch so it doesn't
// know that oFoo is actually of type Foo.
//
// In languages with multiple dispatch, the type of oFoo will
// also be used in runtime so Baz.Zap(Foo) will be called
// instead of Baz.Zap(object)
object oFoo = foo;
Assert.AreEqual("zap object", zapper.Zap(oFoo));
}
public class Zapper
{
public virtual string Zap(object o) { return "generic zapper" ; }
public virtual string Zap(Foo f) { return "generic zapper"; }
}
public class Baz : Zapper
{
public override string Zap(object o) { return "zap object"; }
public override string Zap(Foo f) { return "zap foo"; }
}
public class Foo { }
}
}
При множественной диспетчеризации у метода может быть передано несколько аргументов, и какая реализация используется, зависит от типа каждого аргумента. Порядок оценки типов зависит от языка. В LISP он проверяет каждый тип от первого до последнего. Языки с множественной диспетчеризацией используют универсальные функции, которые являются просто объявлениями функций и не похожи на универсальные методы, которые используют параметры типа.
Многократная диспетчеризация учитывает полиморфизм подтипов аргументов для вызовов методов.
Одиночная диспетчеризация также допускает более ограниченный тип полиморфизма (использование одного и того же имени метода для объектов, которые реализуют один и тот же интерфейс или наследуют один и тот же базовый класс). Это классический пример полиморфизма, где у вас есть методы, которые переопределены в подклассах.
Помимо этого, дженерики предоставляют полиморфизм параметрического типа (т. Е. Один и тот же универсальный интерфейс для использования с различными типами, даже если они не связаны - как List<T>
: это может быть список любого типа и используется одинаково независимо).
Раньше я никогда не слышал о Multiple Dispatch, но после просмотра страницы в Википедии это выглядит так, будто MD - это тип полиморфизма при использовании с аргументами метода.
Полиморфизм - это, по сути, концепция, согласно которой объект можно рассматривать как любой тип, являющийся его основой. Так что если у вас есть Car
и Truck
, они оба могут рассматриваться как Vehicle
, Это означает, что вы можете позвонить любому Vehicle
метод для любого.
Многократная диспетчеризация выглядит аналогично в том смысле, что она позволяет вызывать методы с аргументами нескольких типов, однако я не вижу определенных требований в описании. Во-первых, он не требует общего базового типа (не то чтобы я мог представить реализацию без void*
), и вы можете задействовать несколько объектов.
Поэтому вместо вызова Start()
метод для каждого объекта в списке (который является примером классического полиморфизма), вы можете вызвать StartObject(Object C)
метод, определенный в другом месте, и его код для проверки типа аргумента во время выполнения и соответствующей обработки. Разница здесь в том, что Start()
метод должен быть встроен в класс, а StartObject()
Метод может быть определен вне класса, поэтому различные объекты не должны соответствовать интерфейсу.
Это может быть хорошо, если Start()
метод нужно вызывать с разными аргументами. Может быть Car.Start(Key carKey)
против Missile.Start(int launchCode)
Но оба можно назвать StartObject(theCar)
или же StartObject(theMissile)
Интересная концепция...
Multiple Dispatch больше похож на перегрузку функций (как видно в Java/C++), за исключением того, что вызываемая функция зависит от типа аргументов во время выполнения, а не от их статического типа.
Если вы хотите концептуальный эквивалент вызова метода
(obj_1, obj_2, ..., obj_n)->method
зависеть от каждого конкретного типа в кортеже, то вы хотите многократную отправку. Полиморфизм соответствует случаю n=1 и является необходимой особенностью ООП.
Multiple Dispatch - это разновидность полиморфизма. В Java/C#/C++ есть полиморфизм через наследование и переопределение, но это не множественная диспетчеризация, которая основана на двух или более аргументах (не только this
как в Java/C#/C++)
Multiple Dispatch опирается на полиморфизм на основе. Типичный полиморфизм, встречающийся в C++, C#, VB.NET и т. Д...., использует одну диспетчеризацию - т.е. вызываемая функция зависит только от одного экземпляра класса. Многократная отправка зависит от нескольких экземпляров класса.