Чем отличается полиморфизм от множественной отправки - PullRequest
29 голосов
/ 24 сентября 2008

... или это одно и то же? Я заметил, что у каждого есть своя запись в Википедии: Полиморфизм , Множественная отправка , но мне трудно понять, как эти концепции различаются.

Редактировать: А как Перегрузка вписывается во все это?

Ответы [ 7 ]

41 голосов
/ 24 сентября 2008

Полиморфизм - это средство, которое позволяет языку / программе принимать решения во время выполнения, какой метод вызывать, основываясь на типах параметров, отправленных этому методу.

Количество параметров, используемых языком / средой выполнения, определяет «тип» полиморфизма, поддерживаемого языком.

Одиночная отправка - это тип полиморфизма, при котором для определения вызова используется только один параметр (получатель сообщения - this или self).

Множественная диспетчеризация - это тип полиморфизма, в котором при определении параметров для вызова метода используются несколько параметров. В этом случае приемник, а также типы параметров метода используются, чтобы указать, какой метод вызывать.

Таким образом, вы можете сказать, что полиморфизм - это общий термин, а множественная и единичная отправка - это конкретные типы полиморфизма.

Добавление: перегрузка происходит во время компиляции. Он использует информацию о типе, доступную во время компиляции, чтобы определить, какой тип метода вызывать. Одна / несколько отправок происходит во время выполнения.

Пример кода:

using NUnit.Framework;

namespace SanityCheck.UnitTests.StackOverflow
{
    [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 { }
    }
}
3 голосов
/ 24 сентября 2008

При множественной диспетчеризации у метода может быть передано несколько аргументов, и какая реализация используется, зависит от типа каждого аргумента. Порядок оценки типов зависит от языка. В LISP он проверяет каждый тип от первого до последнего. Языки с множественной диспетчеризацией используют универсальные функции, которые являются просто объявлениями функций и не похожи на универсальные методы, которые используют параметры типа.

Множественная диспетчеризация допускает полиморфизм подтипов аргументов для вызовов методов.

Одиночная диспетчеризация также допускает более ограниченный тип полиморфизма (использование одного и того же имени метода для объектов, которые реализуют один и тот же интерфейс или наследуют один и тот же базовый класс). Это классический пример полиморфизма, где у вас есть методы, которые переопределяются в подклассах.

Кроме того, универсальные предоставляют полиморфизм параметрического типа (т. Е. Один и тот же универсальный интерфейс для использования с различными типами, даже если они не связаны - как List<T>: это может быть список введите и используется одинаково независимо).

2 голосов
/ 24 сентября 2008

Я никогда раньше не слышал о Multiple Dispatch, но после просмотра страницы в Википедии это выглядит так, будто MD - это тип полиморфизма, когда используется с аргументами метода.

Полиморфизм - это, по сути, концепция, согласно которой объект можно рассматривать как любой тип, являющийся его основой. Так что если у вас есть Car и Truck, они оба могут рассматриваться как Vehicle. Это означает, что вы можете вызвать любой метод Vehicle для любого из них.

Множественная диспетчеризация выглядит аналогично в том смысле, что она позволяет вам вызывать методы с аргументами нескольких типов, однако я не вижу определенных требований в описании. Во-первых, похоже, что он не требует общего базового типа (не то чтобы я мог представить реализацию THAT без void*), и вы можете задействовать несколько объектов.

Таким образом, вместо вызова метода Start() для каждого объекта в списке (который является примером классического полиморфизма), вы можете вызвать метод StartObject(Object C), определенный в другом месте, и кодировать его для проверки типа аргумента во время выполнения и обработки это соответственно. Разница здесь в том, что метод Start() должен быть встроен в класс, а метод StartObject() может быть определен вне класса, поэтому различные объекты не должны соответствовать интерфейсу.

Это может быть хорошо, если метод Start() нужно вызывать с другими аргументами. Может быть Car.Start(Key carKey) против Missile.Start(int launchCode)

Но оба можно назвать StartObject(theCar) или StartObject(theMissile)

Интересная концепция ...

1 голос
/ 24 сентября 2008

, если вы хотите концептуальный эквивалент вызова метода

(obj_1, obj_2, ..., obj_n)->method

, чтобы зависеть от каждого конкретного типа в кортеже, тогда вы хотите множественную отправку. Полиморфизм соответствует случаю n = 1 и является необходимой особенностью ООП.

1 голос
/ 24 сентября 2008

Multiple Dispatch больше похож на перегрузку функций (как видно из Java / C ++), за исключением того, что вызываемая функция зависит от типа аргументов во время выполнения, а не от их статического типа.

1 голос
/ 24 сентября 2008

Multiple Dispatch - это разновидность полиморфизма. В Java / C # / C ++ есть полиморфизм через наследование и переопределение, но это не множественная диспетчеризация, которая основана на двух или более аргументах (не просто this, как в Java / C # / C ++)

0 голосов
/ 24 сентября 2008

Multiple Dispatch опирается на полиморфизм на основе. Типичный полиморфизм, встречающийся в C ++, C #, VB.NET и т. Д., Использует одну отправку - то есть вызываемая функция зависит только от одного экземпляра класса. Многократная отправка зависит от нескольких экземпляров класса.

...