解释多态性
什么是多态?我不太确定我理解得对不对。
在Python中,我理解的是我可以这样定义参数:
def blah (x, y)
而不需要指定类型,这和Java这样的语言不同,在Java中,它的写法更像是:
public void blah (int x, string y)
我这样理解对吗?
11 个回答
你得到的回答都很不错,解释了什么是多态。我觉得了解它为什么有用也很重要。
在一些没有多态的编程语言中,你可能会遇到这样的情况:你想对不同类型的对象执行本质上相同的操作,但这个操作对每种类型的实现方式却不一样。比如,像Python那样的语法:
def dosomething(thing):
if type(thing)==suchandsuch:
#do some stuff
elif type(thing)==somesuch:
#do some other stuff
elif type(thing)==nonesuch:
#yet more stuff
这样做会有一些问题。最大的问题是,它会导致代码之间的紧密耦合和大量重复。你可能会在代码的很多地方看到同样的一组测试。如果你添加了一个新的类型,也需要支持这个操作,那你就得去找所有有这种条件的地方,添加一个新的分支。而且,你必须能访问所有相关的源代码才能做这些修改。此外,这种条件逻辑很啰嗦,在实际情况下也很难理解。
能简单地写成这样就好:
thing.dosomething()
这样不仅简洁得多,还能让代码之间的耦合变得松散。这个例子/解释主要针对传统的面向对象编程语言,比如Python。在函数式语言中,细节会有些不同,但多态的一般好处大体上是一样的。
希望通过这个例子,你能明白什么是 多态
。在这张图里,所有的对象都有一个方法 说话(Speak)
,但每个对象的实现方式都不一样。多态让你可以这样做,你可以为一个类和它的子类声明一个动作,但对于每个子类,你可以后续写出你想要的具体实现。
要注意,不同的人使用的术语可能不同;特别是在面向对象编程的圈子和编程语言理论的圈子之间,常常会有一些分歧。
一般来说,多态性是指一个方法或函数能够处理不同类型的输入。举个例子,在Integer
类中的add
方法(或者+
运算符)可能是进行整数相加,而在Float
类中的add
方法则是进行浮点数相加,Bignum
类中的add
方法则可以处理任意大小的数字。多态性就是你可以在一个对象上调用add
方法,而不需要知道这个数字具体是什么类型。
一种特定的多态性,通常在函数式编程圈子里叫做参数多态性,在面向对象编程圈子里叫做泛型编程,它的意思是可以对一个对象执行某些操作,而不需要关心它的具体类型。比如,要反转一个列表,你不需要关心列表中元素的类型,只要知道它是一个列表就行。因此,你可以写出通用的(在这个意义上)列表反转代码:它在整数、字符串、组件、任意对象的列表上都能一样工作。但是,你不能写出一种通用的代码来相加列表中的元素,因为元素被解释为数字的方式取决于它们的类型。
另一种多态性,通常在函数式编程圈子里叫做特设多态性(ad-hoc polymorphism),在面向对象编程圈子里常常叫做子类型多态性(虽然这有点限制了这个概念),它的意思是有一个方法或函数可以根据其参数的具体类型(或者对于方法来说,是调用该方法的对象的类型)表现出不同的行为。上面提到的
add
就是特设多态性。在动态类型语言中,这种能力是显而易见的;而静态类型语言往往会有一些限制,比如要求参数是某个特定类的子类(比如Addable
)。
多态性并不是指在定义函数时必须指定类型。这更多是与静态类型和动态类型有关,虽然这并不是问题的本质。动态类型语言不需要类型声明,而静态类型语言通常需要一些类型声明(从Java中需要很多,到ML中几乎不需要)。