多态与多重调度有什么区别?

时间:2008-09-24 02:20:09

标签: oop polymorphism multiple-dispatch double-dispatch

......或者他们是一回事吗?我注意到每个都有自己的维基百科条目:PolymorphismMultiple Dispatch,但我很难看到这些概念有何不同。

编辑: Overloading如何适应这一切?

7 个答案:

答案 0 :(得分:41)

多态性是一种工具,它允许语言/程序在运行时根据发送到该方法的参数类型在哪个方法上调用。

语言/运行时使用的参数数量决定了语言支持的多态性的“类型”。

单一调度是一种多态,其中只使用一个参数(消息的接收者 - thisself)来确定呼叫。

多分派是一种多态,其中多个参数用于确定调用哪个方法。在这种情况下,接收器以及方法参数的类型用于指示调用哪个方法。

所以你可以说多态性是一般术语,多重和单一派遣是特定类型的多态性。

附录:在编译期间发生重载。它使用编译期间可用的类型信息来确定要调用的方法类型。单个/多个调度在运行时发生。

示例代码:

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 { }
    }
}

答案 1 :(得分:3)

使用多个分派,一个方法可以传递多个参数,使用哪个实现取决于每个参数的类型。评估类型的顺序取决于语言。在LISP中,它从头到尾检查每种类型。 具有多个分派的语言使用泛型函数,这些函数只是函数声明,而不像使用类型参数的泛型方法。

多个分派允许方法调用的subtyping polymorphism个参数。

单个调度还允许更有限的多态(对于实现相同接口或继承相同基类的对象使用相同的方法名称)。这是多态的经典示例,其中包含在子类中重写的方法。

除此之外,泛型提供参数类型多态性(即,与不同类型一起使用的相同通用接口,即使它们不相关 - 如List<T>:它可以是任何类型的列表,无论如何使用相同的方式。

答案 2 :(得分:2)

我之前从未听说过Multiple Dispatch,但是在浏览了Wikipedia页面之后,当与方法的参数一起使用时,它看起来很像MD是一种多态性。

多态性本质上是一个概念,即一个对象可以看作是它的基础类型。因此,如果您有CarTruck,则可以将它们都视为Vehicle。这意味着您可以为任何一个调用任何Vehicle方法。

多个调度看起来类似,因为它允许您使用多种类型的参数调用方法,但是我没有在描述中看到某些要求。首先,它似乎不需要一个共同的基本类型(不是我可以想象在没有void*的情况下实现它)并且你可以涉及多个对象。

因此,不是在列表中的每个对象上调用Start()方法(这是一个经典的多态性示例),而是可以调用其他地方定义的StartObject(Object C)方法并对其进行编码以检查参数类型运行时间并适当地处理它。这里的区别在于Start()方法必须构建在类中,而StartObject()方法可以在类之外定义,因此各种对象不需要符合接口。

如果需要使用不同的参数调用Start()方法,这可能会很好。可能是Car.Start(Key carKey)Missile.Start(int launchCode)

但两者都可以称为StartObject(theCar)StartObject(theMissile)

有趣的概念......

答案 3 :(得分:1)

Multiple Dispatch是一种多态性。在Java / C#/ C ++中,通过继承和覆盖存在多态性,但这不是多分派,它基于两个或多个参数(不仅仅是this,就像在Java / C#/ C ++中一样)

答案 4 :(得分:1)

Multiple Dispatch更类似于函数重载(如Java / C ++中所见),除了调用的函数取决于参数的运行时类型,而不是它们的静态类型。

答案 5 :(得分:1)

如果你想要方法调用的概念等价物

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

依赖于元组中的每个特定类型,那么您需要多次调度。多态性对应于n = 1的情况,是OOP的必要特征。

答案 6 :(得分:0)

Multiple Dispatch依赖于基于多态的。在C ++,C#,VB.NET等中遇到的典型多态性使用单个调度 - 即被调用的函数仅依赖于单个类实例。多个分派依赖于多个类实例。