关于python:解释多态性

Explain polymorphism

什么是多态性?我不确定我是否理解正确。

在python范围内,我可以从中得到如下定义参数:

1
def blah (x, y)

不必指定类型,而不是像Java那样的另一种语言,它看起来更像是:

1
public void blah (int x, string y)

我说得对吗?


请注意,不同的人使用不同的术语;特别是,面向对象的社区和(其余的)编程语言理论社区之间常常存在分歧。

一般来说,多态性意味着一个方法或函数能够处理不同类型的输入。例如,Integer类中的add方法(或+运算符)可能执行整数加法,而Float类中的add方法执行浮点加法,Bignum类中的add方法对任意大小的数字执行正确的运算。多态性是在不知道对象是什么类型的数字的情况下对对象调用add方法的能力。

  • 一种特殊的多态性,通常在功能团体中被称为参数多态性,在OOP团体中被称为通用编程,它能够在不考虑对象的精确类型的情况下对对象执行某些操作。例如,要反转一个列表,您不需要关心列表元素的类型,只需要知道它是一个列表。因此,您可以编写通用(从这个意义上说)列表反转代码:它将在整数、字符串、小部件、任意对象等的列表上相同地工作。但是您不能编写以通用方式添加列表元素的代码,因为元素被解释为数字的方式取决于它们是什么类型。

  • 另一种多态性,通常被称为功能团体中的特殊多态性或(至少对某些形式的多态性)通用编程,并且通常在OOP团体中对多态性进行子类型化(尽管这在一定程度上限制了概念),它能够有一个单独的方法或函数,其行为因精确性而不同。其参数的类型(或者,对于方法,是其方法被调用的对象的类型)。上面的add示例是特殊多态性。在动态类型语言中,这种能力不用说;静态类型语言倾向于(但不必)有一些限制,比如要求参数是某个特定类(Addable的子类)。

多态性不需要在定义函数时指定类型。这与静态类型和动态类型更相关,尽管这不是问题的固有部分。动态类型化的语言不需要类型声明,而静态类型的语言通常需要一些类型声明(从Java中的很多内容到ML中几乎没有)。


希望通过这个例子,您可以理解Polymorphism是什么。在这张图中,所有对象都有一个方法Speak(),但每个对象都有不同的实现。多态性允许您这样做,您可以为一个类及其子类声明一个操作,但是对于每个子类,您可以稍后准确地编写您想要的内容。

Polymorphism


你得到的答案是好的,并解释什么是多态性。我认为这也有助于理解它有用的一些原因。

在一些缺乏多态性的语言中,您会发现自己处于这样的情况:您希望对不同类型的对象执行概念上相同的操作,在这种情况下,必须对每种类型执行不同的操作。例如,在类似于python的语法中:

1
2
3
4
5
6
7
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

这有一些问题。最大的问题是它会导致非常紧密的耦合和大量的重复。在代码的很多地方,您可能都有相同的测试集。如果添加必须支持此操作的新类型,会发生什么情况?你必须找到每一个你有这种条件的地方,然后添加一个新的分支。当然,您必须能够访问所有涉及的源代码,才能进行这些更改。除此之外,这种条件逻辑是冗长的,在实际情况下很难理解。

能写书就更好了:

1
thing.dosomething()

除了短得多,这会导致耦合更松。这个例子/解释面向传统的OO语言,比如Python。比如说,功能语言的细节有点不同。但多态性的许多一般用途仍然是相同的。


多态性的字面意思是"许多形状",这在解释它的用途上相当不错。多态性背后的思想是,可以对不同的类型使用相同的调用,并使它们行为适当。

区别于类型系统是很重要的——强类型语言要求通过继承链将对象关联为多态的,但是对于弱类型语言,这是不必要的。

在Java(等)中,这就是为什么接口是有用的——它们定义了可以在对象上调用而不指定确切对象的函数集——实现该接口的对象相对于该接口是多态的。

在python中,由于事物是动态类型化的,所以接口的形式就不那么正式,但其思想是相同的——调用foo()将在两个知道如何正确实现foo()的对象上成功,但我们不关心它们的真正类型。


不,那不是多态性。多态性是这样一个概念,即一个可执行单元可以有许多不同的实现,在没有调用方意识的情况下,差异就发生在场景的后面。

例如,bird和plane是FlyingObject。所以FlyingObject有一个方法调用fly(),bird和plane都实现fly()方法。bird和plan的飞行方式不同,因此实现方式不同。从客户的角度来看,无论鸟或飞机如何飞行,他们都可以直接调用一个FlyingObject对象的fly()方法,不管该对象是Plan还是Bird。

您所描述的是动态和静态类型检查,类型兼容性分别在运行时和编译时完成。

希望这样。纳瓦曼


简短的回答:为某些目的将不同类型的编程类型实例视为相同的能力。

长答案:来自古希腊的poly(many)+morph(form)+ism。

多态性是一种通用的技术,能够以某种方式对不同的类型进行统一的处理。编程界的例子包括:

  • parametric polymorphism(见Java中的泛型
  • 在Java中实现的EDOCX1 1使用动态消息调度在对象实例之间。
  • ad-hoc
    polymorphism
    ,与能够定义相同的名称只因类型而异它们处理(Java中的重载)。

多态性这个词也用于描述其他不相关领域的概念,如遗传学。


你所说的是自动输入——或者可能是类型检测。这是动态语言倾向于做的事情——它允许用户在构建时不知道或不关心类型——类型是在运行时计算出来的,不局限于特定的类型。

多态性是指您拥有两个从主类继承的类,但每个类都实现了不同的方法。

例如,如果您将车辆作为根类,汽车和自行车作为实例,那么vehicle.calculateDistance()将根据可用的气体(如果车辆是汽车的实例)进行操作,如果是自行车类型,则将根据骑车人的耐力进行操作。

一般是这样使用的:

1
2
3
4
getTotalDistance(Vehicle[] vehicle) {
    int dist=0
    for each vehicle
        dist+=vehicle.calculateDistance();

请注意,您正在传入基类型,但实例永远不会是车辆本身,而是始终是车辆的子类——但您不会将其强制转换为子类型。多态性意味着载体会变形成任何需要孩子的东西。


是的,这是"类型多态性"的一个例子。然而,在谈到面向对象编程时,"多态性"通常与"子类型多态性"有关,您给出的示例通常称为"类型化"。

Java、C、C++等都使用静态类型。在这种情况下,必须指定类型是编译时的。

python和ruby使用dynamic,因为类型是在解释过程中推断出来的。

子类型多态性或仅仅是"多态性"是一个派生类型的基类引用正确调用派生类型的方法的能力。

例如(在接近伪代码中):

1
2
3
4
5
6
7
8
9
10
11
12
13
class Base
{
  virtual void Draw() { //base draw}
}

class Derived: public Base
{
  void Draw() { //derived draw}
}

Base* myBasePtr = new Derived();

myBasePtr->Draw(); //invokes Derived::Draw(), even though it's a base pointer.

这就是多态性。


多态性-同一个对象根据其所处的场景的不同而执行不同的操作。例如,如果一个12岁的孩子和一群孩子在一个房间里,他们听的音乐类型将不同于一个12岁的孩子在一个充满成人的房间里。12岁的孩子是一样的,但是孩子的行为是不同的,基于不同的场景(不同的音乐)。


多态性:

  • 一个方法调用适用于多个类,即使这些类需要不同的实现;
  • 能够提供一个操作的多个实现,并根据周围环境选择正确的实现;
  • 提供重载和重写;
  • 在运行时和编译时都可能发生;
    • 运行时多态性:运行时多态性也称为方法重写方法重写意味着拥有两个或多个具有相同名称、相同签名但具有不同实现的方法
    • 编译时多态性:编译时多态性也称为方法重载方法重载意味着有两个或多个具有相同名称但具有不同签名的方法
  • 在计算机科学中,多态性是一种编程语言特性,它允许使用统一的接口处理不同数据类型的值。参数多态性的概念适用于数据类型和函数。一个可以对不同类型的值进行评估或应用于不同类型的值的函数称为多态函数。可以看似是通用类型的数据类型(例如,具有任意类型元素的列表)被指定为多态数据类型,如进行此类专门化的通用类型。
  • 多态性的缺点:
    • 多态性降低了程序的可读性。我们需要可视化程序的运行时行为,以识别所涉及的实际执行时间类。在实现这个概念的类中导航也变得困难。即使是Sofastiated IDE也不能提供此导航功能。这在一定程度上增加了维护成本。

以多种形式定义函数的能力称为多态性。在C语言中,Java、C++有两种类型的多态性:编译时多态(重载)和运行时多态(重写)。

重写:当类方法与父类中的方法具有相同的名称和签名时,将发生重写。

重载:重载是在编译时确定的。当多个方法具有相同的名称时,会发生这种情况:

  • 不同的方法签名和不同的编号或类型参数。
  • 方法签名相同,但参数数目不同。
  • 相同的方法签名和相同数量的参数,但类型不同