多态性不同于方法重载或方法重写。

8
“多态性”并不等同于方法重载或方法覆盖。 …… 它们本身都不是多态的实现方式。
这是wikipedia上的一句话引文。
然而,在书籍《面向对象编程》中,Timothy Budd指出有“四种不同形式的多态性”:
- 重载(包括多路分派) - 覆盖(包括子类型多态) - 多态变量(赋值多态) - 泛型
到底哪一个是正确的呢?谢谢。

1
这取决于你所说的“多态”的含义。请参见https://dev59.com/w0_Sa4cB1Zd3GeqP_1uD。 - unquiet mind
5
等等……不同的来源与维基百科相矛盾了?吸口气 - FrustratedWithFormsDesigner
看起来他们对术语的定义不同,只要在开始时了解对话的上下文和定义,这两种定义都可能是正确的。问题在于,当A开发者认为维基百科的定义更准确,而B开发者认为Budd先生的定义更准确,而没有相互沟通这些决定时就会出现问题。 - FrustratedWithFormsDesigner
@unquiet mind - 谢谢,我阅读了您链接中被接受的答案,其中指出:“多态(简单地说)是使用派生类替代基类的可能性”。这是否意味着在像Ruby这样的动态语言中,没有“预期”的类,因此多态不适用? - Question
@问题 - 像Ruby这样的动态语言的特性并不意味着您的代码不需要某些类。即使编译器不强制类型,也不意味着您的代码在某个特定时间不需要某个特定类存在。因此,您的答案是“不 - 多态仍然适用,因为动态代码本身仍然可以在任何特定位置‘期望’某种类型”。 - Andrew Barber
显示剩余2条评论
3个回答

3

多态是编程语言的特征或功能。编程语言要么支持它,要么不支持。由于编程语言属于有时存在根本不同范式的范畴,不同的范式(如函数式编程或面向对象编程)可能对该特性的表达和应用略有不同。

据我所知,在面向对象编程中,多态被认为是基本原则之一,也是非常独特的原则之一。大多数面向对象语言都具有多态作为其众多特性之一。简而言之,当带有多态实现的对象的调用者不知道对象的确切类型时,最好看到多态。这通常是继承和强制类型转换的结果,也被称为子类型多态, 通过使用vTables来实现。

我认为(和许多作者一样)运算符重载是多态的一种表现形式。因此,如果您重载 == 运算符以使用 TypeA == TypeB,那么在比较包含类型 A 或 B 的随机元素的列表中的元素时,如果您将 TypeB 视为 TypeA,那么实际上不会关心输入内容,因为它们都可以用于相等性处理。像许多其他争论一样,这个问题有支持者和反对者。
但这就是面向对象编程的故事的结局。
在函数式(声明式)语言(Lisp、F#)中,由于函数是一级公民(而不是对象),多态性通过函数之间的关系来表达,并且表现方式略有不同。请参见Type Polymorphism 我想说的最后一句话是,我和其他人一样喜欢维基百科,但您必须始终带着怀疑的态度看待文章,并且不要盲目相信它们,而要确认其他来源。如果您想了解面向对象编程的真正原则,请从这里开始:Object-Oriented Software Construction (Bertrand Meyer)

1

我相信关于多态性我看过的最好的定义之一是指对象的类型在运行时确定。这似乎强调了对象的运行时类型可能与其声明的类型不同,并且在运行时过程中调用的方法将与对象匹配。


好的,谢谢。这是否意味着像 Ruby 这样只有“运行时”的动态语言不适用多态性?这是否都被认为是鸭子类型? - Question
@问题 在这个关于Ruby中多态性的讨论中,我似乎得到了一个与Java中多态性工作方式非常相似的想法。它几乎像是一种设计模式,而不是与特定语言相关的(有点)。 请查看这个关于Ruby中多态性的讨论: https://dev59.com/mnVC5IYBdhLWcg3w9GA9 - Bnjmn
感谢您提供的链接Bnjmn,我已经阅读了这篇文章。它似乎证实了多态可以通过“与C#中相同的方式使用类和重写方法”来实现。这将使维基百科的定义是错误的,对吗? - Question
@问题 我不确定我会认为维基百科的条目是错误的。它提到,“在面向对象编程的上下文中,多态性是一种类型A能够以另一种类型B的形式出现并被使用的能力。”这与我们迄今讨论的内容一致,它还说:“在弱类型语言中,类型是隐式多态的。”这也还没有问题。那么定义的哪个部分让你感到不舒服呢? - Bnjmn
明白了,谢谢。在 Ruby 中没有静态类型,因此它是“隐式多态的”。我仍然想知道 Ruby 中的多态是否包括重写/重载方法?很抱歉在这里反复强调,但维基百科的条目似乎断言它们不是多态的,但在我看来它们绝对是多态的。它们涉及将方法调用从一个对象更改为另一个对象? - Question
1
@问题 我会投票说,覆盖/重载仍然是多态的,因为原则在这里似乎最重要。毕竟,多态不是指Ruby或Java,而是一种通用的面向对象方法论。 - Bnjmn

1

我将把确切的定义留给更了解的人(从完全纯粹主义的角度),但从纯语义的角度来看,这些陈述并不一定相互矛盾。

其中一个列出了某物的“四种不同形式”,而另一个则说这四种形式中的两种“本身”并不包括该物。有人可能会认为,“四种形式”的作者并不一定是在说每种形式本身都是整体的“完整”例子,而是它们是组成部分。


话虽如此,我认为“四种形式”的作者更正确,而维基百科的作者可能只是试图解析一些过于复杂的东西。你也是一样。:p


继承在整个讨论中有点被默认了,不是吗?就像拥有类一样被默认了。 - Andrew Barber
@Andrew - 是的,我想是这样的,但正如下面有人提到的,“重载”并不一定要使用继承或类来实现。您是否知道您提到的其他要求,可以使其“完全”多态?感谢您的帮助。 - Question
所以,正如我所说:继承和类在重载、覆盖和多态的讨论中是假定的。后三者没有前两者就没有意义。进一步思考:多态、重载和覆盖需要“编程”吗?当然需要!(但编程并不需要这些) - Andrew Barber
我已经多次非常简洁地回答了你的问题。如果某事被“假定”,难道不清楚地表明它是“涉及”的吗?但问题在于,你的问题揭示了对术语关系的理解不足,而我正在努力帮助你理解它们。显然,我的尝试失败了,所以我会停止。 - Andrew Barber
我会仔细查看这两位作者提到的所有不同事物;将那些常见的列出来,把它们作为起点考虑。正如我在回答开头所建议的那样,对于纯粹主义者而言,我无法提供100%“正确”的答案,但我认为“四种形式”的作者更接近你引用的内容。 - Andrew Barber
显示剩余4条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接