【问题标题】:What's the difference between Polymorphism and Multiple Dispatch?多态性和多分派有什么区别?
【发布时间】:2010-09-12 14:36:03
【问题描述】:

...或者它们是同一个东西?我注意到每个都有自己的 Wikipedia 条目:PolymorphismMultiple Dispatch,但我很难看出这些概念有何不同。

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

【问题讨论】:

    标签: oop polymorphism multiple-dispatch double-dispatch


    【解决方案1】:

    多态是允许语言/程序在运行时根据发送给该方法的参数类型决定调用哪个方法的工具。

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

    单分派是一种多态性,其中仅使用一个参数(消息的接收者 - 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 { }
        }
    }
    

    【讨论】:

    • 出色的答案! A++++++ 会再次询问
    • 谢谢!这帮助我整理了我在维基百科上阅读的概念。
    【解决方案2】:

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

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

    单次分派还允许一种更有限的多态性(对实现相同接口或继承相同基类的对象使用相同的方法名称)。这是多态性的经典示例,其中您的方法在子类中被覆盖。

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

    【讨论】:

      【解决方案3】:

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

      【讨论】:

        【解决方案4】:

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

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

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

        因此,您可以调用在其他地方定义的StartObject(Object C) 方法并对其进行编码以在运行时检查参数类型并处理它适当地。这里的区别是Start()方法必须内置在类中,而StartObject()方法可以定义在类之外,因此各种对象不需要符合接口。

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

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

        有趣的概念...

        【讨论】:

          【解决方案5】:

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

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

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

          【讨论】:

            【解决方案6】:

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

            【讨论】:

              【解决方案7】:

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

              【讨论】:

                猜你喜欢
                • 2016-09-30
                • 2015-01-19
                • 1970-01-01
                • 2012-07-15
                • 1970-01-01
                • 2010-09-26
                • 2022-09-27
                • 2014-03-30
                相关资源
                最近更新 更多