什么是多态性?它的用途是什么?


564

什么是多态性?它的用途是什么?


19
@John:+1我同意这是一个最有趣的现象。我敢肯定,Unkwntech并不是唯一一个知识渊博的,有能力的人,在别人认为是基本词汇的方面尚有差距。只是显示编程是一个非常广泛的主题。
AnthonyWJones

9
他可能会使用它,只是不给它起一个名字。
艾登·贝尔

10
@Aamir:我不确定有8k的人会知道所有编程领域的所有基本知识是否合理。我也不认为这表明声誉系统是不完善的。通过提出很多好的问题,某人可以获得很高的声誉。我认为我们对这个启示的自然反应只是表明我们(程序员)天生就有一点狭narrow的倾向(当我们在某些特定技术领域需要真正优秀时,这不是一件坏事),并且有其缺点。
AnthonyWJones

43
你们似乎对编程的看法非常有限。我知道从事嵌入式开发的人根本不了解(或不需要)OO概念。他们的简介是从代码中获取性能的每一个最后要素,仅此而已-他们正在处理的代码将永远不会进入对象的世界,而且幸运的是它们已经接近退休,他们不必担心学习带有两个以上字母的新概念,例如对象,多态性和变量名:-)
paxdiablo

29
如何你学习的东西?没有人知道PHP OOP和设计模式,因此所有人在某个时候都必须学习它,在大学里,在这里找到答案,等等。不要谈论“敢于不知道复杂代码过程的人” ”,而是考虑他们在这里想要学习它,这是一件好事,也是本网站的重点。浪费时间帮助他们,因为我相信您过去曾经得到过帮助。如果在人类的整个历史中,不是分享知识,而是说“什么?哈!你不知道吗?”。我们所有人都仍处于黑暗时代
詹姆斯

Answers:


544

如果您考虑该术语的希腊语根源,应该会很明显。

  • 聚=许多:多边形=多面,聚苯乙烯=许多苯乙烯(a),多色=许多语言,依此类推。
  • 形态=变化或形式:形态=对生物形式的研究,Morpheus =能够采取任何形式的希腊梦之神。

因此,多态性是(在编程中)针对不同底层形式(数据类型)呈现相同接口的能力。

例如,在许多语言中,整数和浮点数都是隐式多态的,因为您可以加,减,乘等等,而与类型不同的事实无关。通常,它们很少被视为对象。

但是,在同样的方式,就像一个类BigDecimalRational或者Imaginary也可以提供这些业务,即使他们在不同的数据类型进行操作。

经典示例是Shape类以及可以从中继承的所有类(正方形,圆形,十二面体,不规则多边形,splat等)。

使用多态性,这些类中的每一个将具有不同的基础数据。点形状仅需要两个坐标(假设它在二维空间中)。圆需要一个中心和半径。正方形或矩形需要两个坐标用于左上角和右下角,以及(可能)旋转。不规则多边形需要一系列线。

通过使类负责其代码及其数据,可以实现多态。在此示例中,每个类都有其自己的Draw()功能,并且客户端代码可以简单地执行以下操作:

shape.Draw()

以获得任何形状的正确行为。

这与旧的处理方式相反,在旧的处理方式中,代码与数据是分开的,您将拥有诸如drawSquare()和的功能drawCircle()

面向对象,多态性和继承都是紧密相关的概念,了解它们至关重要。在我漫长的职业生涯中,有很多“银子弹”基本上都消失了,但是面向对象范例已经证明是一个不错的选择。学习,理解,喜欢它-您会很高兴的:-)


(a)我最初是作为一个玩笑而写的,但事实证明是正确的,因此并不那么有趣。单体苯乙烯恰好由碳和氢制成,而聚苯乙烯则由这些基团制成。C8H8(C8H8)n

也许我应该说息肉是这封信的多次出现,p但是,既然我不得不解释这个笑话,即使那也不是很有趣。

有时,您应该在落后的时候退出:-)


50
希腊语,而不是拉丁语:)(“ y”和“ ph”是赠品)。而在希腊,“morph-”是只是 “形”,或“形式” -英文的意思是“的变化形”的“变身”为以后的发展
AakashM

16
多态与OOP不相关,但是OOP与多态有关,因为它固有地支持它(假定它是一种体面的OOP语言)。在FP中查看多态的其他示例。
替代

9
这2行对我Poly = many and Morph = change or form
有用

3
息肉是息肉的缩写。脚踩在希腊。;-)
Dirk

2
@Shaun,我想您可能会在字面上/狭义上使用“接口”一词-我的意思是说它是一个英文术语,而不是特定于某些任意计算机语言的定义。这并不意味着具有完全相同的参数的完全相同的函数,它只是一种以相同的方式影响“对象”的方法,而与它们的基础具体类型无关。这可以包括具有不同参数类型的方法重载以及更纯净的多态形式。
paxdiablo '17

250

多态是指您可以将对象视为某物的通用版本,但是当您访问它时,代码将确定其确切的类型并调用关联的代码。

这是C#中的示例。在控制台应用程序中创建四个类:

public abstract class Vehicle
{
    public abstract int Wheels;
}

public class Bicycle : Vehicle
{
    public override int Wheels()
    {
        return 2;
    }
}

public class Car : Vehicle
{
    public override int Wheels()
    {
        return 4;
    }
}

public class Truck : Vehicle
{
    public override int Wheels()
    {
        return 18;
    }
}

现在,在控制台应用程序的模块的Main()中创建以下代码:

public void Main()
{
    List<Vehicle> vehicles = new List<Vehicle>();

    vehicles.Add(new Bicycle());
    vehicles.Add(new Car());
    vehicles.Add(new Truck());

    foreach (Vehicle v in vehicles)
    {
        Console.WriteLine(
            string.Format("A {0} has {1} wheels.",
                v.GetType().Name, v.Wheels));
    }
}

在此示例中,我们创建了一个基类Vehicle的列表,该列表不知道每个子类有多少个车轮,但是知道每个子类负责知道它有多少个车轮。

然后,我们将自行车,汽车和卡车添加到列表中。

接下来,我们可以遍历列表中的每个Vehicle,并对其进行相同的处理,但是,当我们访问每个Vehicles'Wheels'属性时,Vehicle类会将代码的执行委托给相关的子类。

该代码被称为多态的,因为执行的确切代码由运行时引用的子类确定。

希望对您有帮助。


6
我认为这是一个很好的示例,可以清楚地显示父界面,并且直到实例化该对象后才需要一个具体的版本,即Vehicle vs car
–wire00

1
我想说的是最清楚的例子,尽管如果您是PHP程序员,则此链接可能更易于查看“第一”,然后在之后仍然查看此链接:code.tutsplus.com/tutorials/…–
Oliver Williams,

另外(超出OP的范围)要注意,我们将分析限制在已知对象上。我们没有传递对象(例如导入文件),而是确定它是什么类型(Excel,CSV,YAML,SQL等)。要做到这一点人们会需要一些工厂类的Class_ExcelClass_CSV被称为,或有一个Reader叫做类。无论哪种方式,都必须将某种迭代的if / then / else存储在某个地方。
奥利弗·威廉姆斯

@Antony Gibbs:这是一个非常不错的示例(泛型类型列表),对我来说很有意义……否则,让每个类都拥有自己的wheel函数而不继承基类有什么重要意义?除了列表之外,还有其他适用于多态的概念吗?
TTT

195

了解和应用PHP中的多态性,感谢Steve Guidetti。

对于一个非常简单的概念,多态性是一个长词。

多态描述了面向对象编程中的一种模式,其中的类在共享公共接口的同时具有不同的功能。

多态的好处在于,使用不同类的代码不需要知道正在使用哪个类,因为它们都以相同的方式使用。现实世界中对多态性的类比是一个按钮。每个人都知道如何使用按钮:您只需向按钮施加压力。但是,按钮的“作用”取决于它所连接的对象以及使用它的上下文,但是结果并不影响它的使用方式。如果老板告诉您按下按钮,则您已经拥有执行任务所需的所有信息。

在编程世界中,多态性用于使应用程序更具模块化和可扩展性。您可以创建根据需要选择的可互换对象,而不必使用混乱的条件语句来描述不同的操作过程。这是多态性的基本目标。


10
按钮类比与抽象概念是否更多相关?
thewpfguy


8
@Mantriur:这确实是窃,我们对此有反对的规则:stackoverflow.com/help/referencing但是鉴于其得分,以及删除答案后旧帖子免于代表损失的事实,我不确定是否删除它现在彻底改善任何事情。下一个最佳选择是仅代表用户编辑归因,即使我坚信用户有责任在自己的答案中引用来源。
BoltClock

1
我认为暗示多态性是特定于类和/或面向对象的程序的,这是不正确的,因为看到了即席多态性或参数多态性不一定需要类和/或对象。我认为这个答案在谈论的是子类型化(也称为子类型多态或包含多态)。
StubbornShowaGuy

64

如果有人对这些人说

  1. 外科医生
  2. 发型师
  3. 演员

会发生什么?

  • 外科医生将开始做切口。
  • 发型师将开始修剪某人的头发。
  • 演员会突然停止在当前场景外表演,等待导演指导。

因此,以上表示显示了OOP中的什么是多态(同名,不同行为)。

如果您要去面试,而面试官要求您在我们坐在的同一个房间里讲/展示多态性的现场示例,请说-

答案-门/窗户

想知道如何?

通过门/窗-一个人可以来,空气可以来,光可以来,雨可以来,等等。

为了更好地理解它并以一种简单的方式,我使用了上面的示例。如果您需要代码参考,请遵循上面的答案。


5
我认为这不是一个很好的例子,因为它可能会使没有经验的人认为如果两个类都有一个.foo()方法,那么他们应该共享一个公共接口。但是,这不是真的,并且会导致错误的抽象。接口应定义要扮演的角色,该角色可能具有许多不同的实现,但是所有角色都从同一组输入中提取并从同一组输出中返回某些内容。输入到x.cut(...)外科医生,设计师,或演员是不一样的,也不是输出。
马特·克莱因

37

类推简单解释

美国总统采用多态性。怎么样?好吧,他有很多顾问:

  1. 军事顾问
  2. 法律顾问
  3. 核物理学家(作为顾问)
  4. 医疗顾问
  5. 等等等

每个人都应该只对一件事负责:示例:

总统不是镀锌或量子物理学方面的专家。他不知道很多事情-但他只知道一件事:如何管理国家。

代码也是如此:关注点和责任应该与相关的类/人员分开。否则,您将让总统真正了解世界上的一切-整个Wikipedia。想象一下,将整个Wikipedia放在代码类中:维护它将是一场噩梦。

为什么对于总统来说,要了解所有这些具体情况,这是一个坏主意?

如果总统都明确告诉人们要做什么,这将意味着,总统需要知道该怎么做。如果总统需要亲自了解具体情况,这意味着当您需要进行更改时,您将需要在两个地方进行改变,而不仅仅是一个地方。

例如,如果EPA更改了污染法规,则在这种情况发生时:您必须更改EPA班级以及总统班级。在两个地方而不是一个地方更改代码可能会很危险-因为这很难维护。

有没有更好的方法?

有一个更好的方法:总统不需要知道任何事情的细节-他可以从专门负责这些事情的人那里寻求最好的建议。

他可以使用多态方法来管理国家。

示例-使用多态方法:

总统要做的就是请人们提供建议-这就是他在现实生活中实际上所做的-这就是一个好的总统应该做的。他的顾问的反应各不相同,但是他们都知道总统的意思是:Advise()。他有数百人涌入他的办公室。他们到底是谁并不重要。总统所知道的就是,当他要求他们“建议”时,他们知道如何做出相应的反应

public class MisterPresident
{
    public void RunTheCountry()
    {
        // assume the Petraeus and Condi classes etc are instantiated.
        petraeus.Advise(); // # Petraeus says send 100,000 troops to Fallujah
        condolezza.Advise(); // # she says negotiate trade deal with Iran
        healthOfficials.Advise(); // # they say we need to spend $50 billion on ObamaCare
    }
}

这种方法使总统可以在没有任何军事知识,医疗保健或国际外交知识的情况下直接运营国家:细节留给专家。总统唯一需要知道的是:“ Advise()”。

您不想要的:

public class MisterPresident
{
    public void RunTheCountry()
    {
        // people walk into the Presidents office and he tells them what to do
        // depending on who they are.

        // Fallujah Advice - Mr Prez tells his military exactly what to do.
        petraeus.IncreaseTroopNumbers();
        petraeus.ImproveSecurity();
        petraeus.PayContractors();

        // Condi diplomacy advice - Prez tells Condi how to negotiate

        condi.StallNegotiations();
        condi.LowBallFigure();
        condi.FireDemocraticallyElectedIraqiLeaderBecauseIDontLikeHim();

        // Health care

        healthOfficial.IncreasePremiums();
        healthOfficial.AddPreexistingConditions();
    }
}

没有!没有!没有!在上述情况下,总统正在做所有工作:他知道增加部队人数和现有条件的情况。这意味着,如果中东政策改变,那么总统将不得不改变他的命令,以及彼得雷乌斯阶级。我们只需要改变彼得雷乌斯阶级,因为总统不必在细节上陷入困境。他不需要了解细节。他所需要知道的就是,如果他下订单,一切都会得到照顾。所有细节应留给专家。

这使总统可以做他最擅长的事情:制定总体政策,看起来不错,打高尔夫球:P。

它是如何实际实现的-通过基类或公共接口

简而言之,实际上是多态性。到底是怎么做的?通过“实现公共接口” 通过使用基类(继承)-请参阅上面的答案,该答案将更详细地说明这一点。(为了更清楚地理解这个概念,您需要了解什么是接口,并且您需要了解什么是继承。否则,您可能会遇到困难。)

换句话说,Petraeus,Condi和HealthOfficials都是“实现接口”的类-我们称它为IAdvisor仅包含一个方法的接口Advise()。但是,现在我们进入细节。

这将是理想的

    public class MisterPresident
    {
            // You can pass in any advisor: Condi, HealthOfficials,
            //  Petraeus etc. The president has no idea who it will 
            // be. But he does know that he can ask them to "advise" 
            // and that's all Mr Prez cares for.

        public void RunTheCountry(IAdvisor governmentOfficer)
        {             
            governmentOfficer.Advise();              
        }
    }


    public class USA
    {
        MisterPresident president;

        public USA(MisterPresident president)
        {
            this.president = president;
        }

        public void ImplementPolicy()
        {
            IAdvisor governmentOfficer = getAdvisor(); // Returns an advisor: could be condi, or petraus etc.
            president.RunTheCountry(governmentOfficer);
        }
    }

摘要

您真正需要知道的是:

  • 总统不需要知道具体细节,这些细节留给别人看。
  • 总统所需要知道的就是问问谁走进门为他提供建议-我们知道,当他们被要求提供建议时,他们将绝对知道该怎么做(因为实际上,他们都是顾问(或IAdvisors :))

我真的希望它能对您有所帮助。如果您什么都不懂,请发表评论,我会再试一次。


4
很棒的例子!谢谢。
伊曼·塞迪吉

1
非常有趣的类比。谢谢。
thanhtang

1
@TTT,因为(1)每当您有一个新的顾问时,您就必须更改总裁班级-您不想进行x2更改。只有一个。(2)其次,如果您必须更改现有的顾问,那么您可能必须返回并更改总裁班中的这三个电话之一-您只想真正更改一次,而不是两个。(3)如果您有三个单独的电话,那么您将不得不在校长班上问:if healthAdvisor? then do this:而且if petraus then do that etc.这种模式将需要重复,这是不必要且复杂的。见上文编辑。
BKSpurgeon

1
@TTT是的,您是对的。但是我必须将这个概念慢慢地介绍给读者,否则他们将无法理解。我添加了进一步的更改。请告知是否需要澄清
BKSpurgeon

1
@TTT基类vs接口是程序员在做多态性时必须做出的设计决策。详情请参阅:stackoverflow.com/questions/56867/interface-vs-base-class
BKSpurgeon

24

多态是一种将对象类视为父类的能力。

例如,假设有一个叫Animal的类,还有一个叫Dog的类,它是从Animal继承的。多态是将任何Dog对象都视为Animal对象的能力,如下所示:

Dog* dog = new Dog;
Animal* animal = dog;

我不知道这与@Ajay Patel给出的(受欢迎的)解释有什么关系classes have different functionality while sharing a common interface
BornToCode 2014年

1
@BornToCode父类是/提供了该公共接口。
grokmann 2014年

1
多态不需要子类型。
Shaun Luttin

22

多态性:

这是面向对象编程的概念。不同对象以相同的方式响应相同消息的能力称为多态。

多态性是由于每个类都位于其自己的名称空间中而导致的。在类定义中分配的名称与在其外部任何地方分配的名称不冲突。对象数据结构中的两个实例变量和对象方法均是如此:

  • 就像C结构的字段位于受保护的命名空间中一样,对象的实例变量也是如此。

  • 方法名称也受到保护。与C函数的名称不同,方法名称不是全局符号。一个类中的方法名称不能与其他类中的方法名称冲突;两个截然不同的类可以实现名称相同的方法。

方法名称是对象接口的一部分。当发送一条消息要求对象执行某项操作时,该消息将命名该对象应执行的方法。因为不同的对象可以使用具有相同名称的方法,所以必须相对于接收消息的特定对象理解消息的含义。发送到两个不同对象的同一消息可以调用两个不同的方法。

多态性的主要好处是它简化了编程接口。它允许建立可以在一个班级又一个班级重用的约定。不必为添加到程序中的每个新功能创建新名称,而是可以重复使用相同的名称。可以将编程接口描述为一组抽象行为,与实现它们的类完全不同。

例子:

示例1:这是一个用Python 2.x编写的简单示例。

class Animal:
    def __init__(self, name):    # Constructor of the class
        self.name = name
    def talk(self):              # Abstract method, defined by convention only
        raise NotImplementedError("Subclass must implement abstract method")

class Cat(Animal):
    def talk(self):
        return 'Meow!'

class Dog(Animal):
    def talk(self):
        return 'Woof! Woof!'

animals = [Cat('Missy'),
           Dog('Lassie')]

for animal in animals:
    print animal.name + ': ' + animal.talk()

示例2:使用方法重载和方法重写概念在Java中实现多态。

让我们以Car为例讨论多态性。以福特,本田,丰田,宝马,奔驰等品牌为例,一切都是汽车类型。

但是每个人的移动行为都具有自己的高级功能和更先进的技术。

现在让我们创建一个基本类型的汽车

汽车.java

public class Car {

    int price;
    String name;
    String color;

    public void move(){
    System.out.println("Basic Car move");
    }

}

让我们实现福特汽车的例子。

福特将Car类型扩展为继承其所有成员(属性和方法)。

福特java

public class Ford extends Car{
  public void move(){
    System.out.println("Moving with V engine");
  }
}

上面的Ford类扩展了Car类,并且还实现了move()方法。尽管可以通过继承对福特使用Move方法,但福特仍然以自己的方式实现了该方法。这称为方法覆盖。

本田

public class Honda extends Car{
  public void move(){
    System.out.println("Move with i-VTEC engine");
  }
}

就像福特一样,本田也扩展了Car类型并以自己的方式实现了move方法。

方法覆盖是启用多态性的重要功能。使用方法覆盖,Sub类型可以更改可通过继承使用的方法的工作方式。

PolymorphismExample.java

public class PolymorphismExample {
  public static void main(String[] args) {
    Car car = new Car();
    Car f = new Ford();
    Car h = new Honda();

    car.move();
    f.move();
    h.move();

  }
}

多态示例输出:

在PolymorphismExample类的main方法中,我创建了三个对象-Car,Ford和Honda。这三个对象都由Car类型引用。

请注意此处的重要一点,超类类型可以引用对象的子类类型,但反之则不可行。原因是超类的所有成员都可以通过继承使用给子类,并且在编译期间,编译器尝试评估我们使用的引用类型是否具有他尝试访问的方法。

因此,对于PolymorphismExample中的引用car,f和h,从Car类型开始存在move方法。因此,编译器顺利通过了编译过程。

但是,当涉及到运行时执行时,虚拟机将在属于子类型的对象上调用方法。因此,从各自的实现中调用方法move()。

因此,所有对象都是Car类型的,但是在运行期间,执行取决于发生调用的对象。这称为多态。


重载概念与继承和多态性无关。
srk

@srk方法重载是实现多态的一种方法。它通常分为静态或临时多态性。wiki.c2.com/?CategoryPolymorphism
Shaun Luttin

12

通常,这是指类型A的对象表现得像类型B的对象的能力。在面向对象的编程中,这通常是通过继承来实现的。一些维基百科链接以了解更多信息:

编辑:修复断开的链接。


10
“类型A的对象的行为类似于类型B的对象的能力”-这不是准确的定义。我会说这更像是治疗A型的对象的能力,喜欢它的类型B的对象
阿尔乔姆·巴格

是。也许这是一个更好的措辞。
JesperE

为了完整起见,许多语言都通过鸭子类型(例如Python)实现多态。
ilya n。

我不知道这与@Ajay Patel给出的(受欢迎的)解释有什么关系classes have different functionality while sharing a common interface
BornToCode 2014年

9

多态是这样的:

class Cup {
   int capacity
}

class TeaCup : Cup {
   string flavour
}

class CoffeeCup : Cup {
   string brand
}

Cup c = new CoffeeCup();

public int measure(Cup c) {
    return c.capacity
}

您只能通过杯赛而不是特定的实例。这有助于提高通用性,因为您不必为每种杯子类型提供特定的measure()实例


2
具体来说,这是亚型多态性。
Shaun Luttin

@ vinko-vrsalovic:美国农村的软件开发如何?
TTT

8

我知道这是一个较老的问题,有很多好的答案,但我想提供一个句子的答案:

将派生类型视为基本类型。

上面有很多示例说明了这一点,但我认为这是一个很好的简洁答案。


2
这是子类型化,这只是一种多态性。
Shaun Luttin

@ShaunLuttin您可以指出我任何资源以更多地了解其他类型的多态性吗?
安倍·米斯勒

除“亚型多态性”外,还有“特设多态性”和“参数多态性”。
Shaun Luttin


5

一般而言,它是使用相同或表面上相似的API来连接许多不同类型的对象的能力。有多种形式:

  • 函数重载:定义多个具有相同名称和不同参数类型的函数,例如sqrt(float),sqrt(double)和sqrt(complex)。在大多数允许这样做的语言中,编译器会针对传递给它的参数类型自动选择正确的参数,因此这是编译时多态性。

  • OOP中的虚拟方法:类的方法可以根据其子类的具体情况进行各种实现;据说这些方法都覆盖了基类中给出的实现。给定一个对象可能是基类或其任何子类,则在运行中选择正确的实现,因此这是运行时多态。

  • 模板:某些OO语言的功能,可以通过类型对函数,类等进行参数化。例如,您可以定义一个通用的“列表”模板类,然后将其实例化为“整数列表”,“字符串列表”,甚至可能是“字符串列表”等。通常,您为任意元素类型的数据结构编写一次代码,然后编译器为各种元素类型生成其版本。


4

术语多态性来自:

聚=许多

态射=改变的能力

在编程中,多态是一种“技术”,可让您“将”对象视为一种以上的事物。例如:

学生对象也是人对象。如果您“看着”学生(即演员),则可能会要求提供学生证。你不能总是和一个人在一起,对吗?(一个人不一定是学生,因此可能没有学生证)。但是,一个人可能有名字。学生也是。

底线,从不同的“角度”“看”同一对象可以给您不同的“视角”(即不同的属性或方法)

因此,该技术使您可以构建可以从不同角度“看”的东西。

我们为什么要使用多态性?对于初学者...抽象。在这一点上,它应该是足够的信息:)


3

让我们用一个比喻。对于给定的音乐剧本,每个演奏它的音乐家都会在演绎中赋予自己的风格。

音乐家可以通过界面进行抽象,音乐家所属的流派可以是一个抽象类,它定义了一些全球性的解释规则,并且每个演奏者都可以用一个具体的类来建模。

如果您是音乐作品的听众,那么您可以参考剧本,例如巴赫(Bach)的“富加和托卡塔(Fuga and Tocata)”,每位演奏该音乐的音乐家都以自己的方式进行多态操作。

这只是一个可能的设计示例(使用Java):

public interface Musician {
  public void play(Work work);
}

public interface Work {
  public String getScript();
}

public class FugaAndToccata implements Work {
  public String getScript() {
    return Bach.getFugaAndToccataScript();
  }
}

public class AnnHalloway implements Musician {
  public void play(Work work) {
    // plays in her own style, strict, disciplined
    String script = work.getScript()
  }
}

public class VictorBorga implements Musician {
  public void play(Work work) {
    // goofing while playing with superb style
    String script = work.getScript()
  }
}

public class Listener {
  public void main(String[] args) {
    Musician musician;
    if (args!=null && args.length > 0 && args[0].equals("C")) {
      musician = new AnnHalloway();
    } else {
      musician = new TerryGilliam();
    }
    musician.play(new FugaAndToccata());
}

1
AnnHallowayVictorBorga感觉它们应该是对象而不是类-您的示例使用eg可以更好地阅读 public class Pianist implements MusicianvictorBorge = new Pianist();
Przemek d

3

我为另一个问题提供了多态性的高级概述:

C ++中的多态

希望能帮助到你。摘录...

...它有助于从一个简单的测试及其[多态性]的定义开始。考虑一下代码:

Type1 x;
Type2 y;

f(x);
f(y);

在这里,f()是执行一些操作并被赋予值xy输入。要实现多态,f()必须能够使用至少两种不同类型(例如intdouble)的值进行操作,以查找并执行适合类型的代码。

(接续c + +中的多态性


3

多态是一种对象的能力,可以采取多种形式。例如,在人类阶级中,当我们谈论关系时,一个人可以采取多种形式。例:一个男人是儿子的父亲,他是妻子的丈夫,也是学生的老师。


3

多态是对象采取多种形式的能力。当使用父类引用来引用子类对象时,会在OOP中最常见地使用多态。在用Java编写的此示例中,我们有三种类型的车辆。我们创建三个不同的对象并尝试运行其wheel方法:

public class PolymorphismExample {

    public static abstract class Vehicle
    {
        public int wheels(){
            return 0;
        }
    }

    public static class Bike extends Vehicle
    {
        @Override
        public int wheels()
        {
            return 2;
        }
    }

    public static class Car extends Vehicle
    {
        @Override
        public int wheels()
        {
            return 4;
        }
    }

    public static class Truck extends Vehicle
    {
        @Override
        public int wheels()
        {
            return 18;
        }
    }

    public static void main(String[] args)
    {
        Vehicle bike = new Bike();
        Vehicle car = new Car();
        Vehicle truck = new Truck();

        System.out.println("Bike has "+bike.wheels()+" wheels");
        System.out.println("Car has "+car.wheels()+" wheels");
        System.out.println("Truck has "+truck.wheels()+" wheels");
    }

}

结果是:

结果

有关更多信息,请访问https://github.com/m-vahidalizadeh/java_advanced/blob/master/src/files/PolymorphismExample.java。希望对您有所帮助。


是的,但是您没有解释多态性的好处。显然有一个较短的代码,您可以在其中删除Vehicle类,并且仍然可以使用(当然,使用不同的对象声明)。
Cornelius

我没有解释,因为提出问题的人没有问到好处。他问:“多态性是什么?它的用途是什么?如何使用它?”。关于代码,如果可以做得更好,请发布答案。因此,我们的社区可以使用它。谢谢你的评论。
穆罕默德

抱歉,不想听起来很粗鲁,其他人也没有解释。至少您不愿意输入代码。无论如何,他问它是做什么用的,但是此页面上的所有示例都没有解释它的用途。你们都只是提出了一种复杂的方法来获得与以下结果相同的结果:s28.postimg.org/jq8vl6031/Poly.jpg却无人问津为什么要使用多态性,它的收益或目的是什么,什么可能没有?不使用就完成了吗?所有我此页面上看到的是使用楼梯爬上去您的公寓一个命题,而不是电梯..
科尼利厄斯

..却没有注意到一个人携带的旗杆太大,无法容纳电梯。我不知道如何发布代码,所以我无济于事...
Cornelius

2

多态是程序员编写具有相同名称的方法的能力,这些方法可以根据对象的需求针对不同类型的对象执行不同的操作。例如,如果您要开发一个名为的类Fraction和名为的类ComplexNumber,则这两个类都可能包含名为的方法display(),但是它们每个都将以不同的方式实现该方法。例如,在PHP中,您可以这样实现:

//  Class definitions

class Fraction
{
    public $numerator;
    public $denominator;

    public function __construct($n, $d)
    {
        //  In real life, you'd do some type checking, making sure $d != 0, etc.
        $this->numerator = $n;
        $this->denominator = $d;
    }

    public function display()
    {
        echo $this->numerator . '/' . $this->denominator;
    }
}

class ComplexNumber
{
    public $real;
    public $imaginary;

    public function __construct($a, $b)
    {
        $this->real = $a;
        $this->imaginary = $b;
    }

    public function display()
    {
        echo $this->real . '+' . $this->imaginary . 'i';
    }
}


//  Main program

$fraction = new Fraction(1, 2);
$complex = new ComplexNumber(1, 2);

echo 'This is a fraction: '
$fraction->display();
echo "\n";

echo 'This is a complex number: '
$complex->display();
echo "\n";

输出:

This is a fraction: 1/2
This is a complex number: 1 + 2i

其他一些答案似乎暗示多态性仅与继承一起使用。例如,也许Fraction并且ComplexNumber都实现了一个名为class的抽象类Number,该抽象类具有一个method display(),然后必须执行Fraction和ComplexNumber。但是您不需要继承即可利用多态性。

至少在动态类型的语言(如PHP(我不了解C ++或Java))中,多态性允许开发人员调用方法而不必事先知道对象的类型,并相信方法的正确实现将叫做。例如,假设用户选择Number创建的类型:

$userNumberChoice = $_GET['userNumberChoice'];

switch ($userNumberChoice) {
    case 'fraction':
        $userNumber = new Fraction(1, 2);
        break;
    case 'complex':
        $userNumber = new ComplexNumber(1, 2);
        break;
}

echo "The user's number is: ";
$userNumber->display();
echo "\n";

在这种情况下,display()即使开发人员无法提前知道用户是选择小数还是复数,也将调用适当的方法。


2
那不是多态。这是两个具有相同名称的方法的类。它们将需要通过称为“可显示”或类似名称的基类或接口进行链接,然后其他方法将只关心对象是“可显示”类型,而不是“复杂”或“分数”类型。

我一直认为多态性 “两个类具有相同命名法的类”。实际上,引用斯蒂芬·科尚(Stephan Kochan)(我毫不掩饰地摘自这个分数/复杂示例),“在不同类之间共享相同方法名称的能力被称为多态性。” (来自Programming_In_Objective-C)他没有提到通过基类链接类的任何需要。老实说,也许不同的语言有所不同。
Alex Basson

即使从出版的书中引用了这种定义,我仍然认为这是不正确的。尤其是因为它似乎彼此冲突,所以与语言无关的多态性定义。尽管最终结果与多态性相同,但我认为,正是动态类型使程序员能够促使人们在其他类似名称的方法中调用方法的正确实现。
vipirtti

2

在面向对象的编程中,多态性是指编程语言根据对象的数据类型或类对对象进行不同处理能力。更具体地说,它是重新定义派生类的方法的能力。


2

多态性从字面上意味着多种形状。(或多种形式):来自不同类和相同名称方法的对象,但是工作流不同。一个简单的例子是:

考虑一个人X。

他只是一个人,但他的行为却很多。您可能会问:

他是他母亲的儿子。朋友对他的朋友。他姐姐的兄弟。


2

OOP中的多态性意味着一类可以具有不同的类型,继承是实现多态性的一种方式。

例如,Shape是一个接口,它具有SquareCircleDiamond子类型。现在您有了一个Square对象,因为Square是Shape,所以可以自动将Square转换为Shape。但是,当您尝试将Shape向下转换为Square时,必须进行显式类型转换,因为您不能说Shape是Square,也可以是Circle。因此,您需要使用像这样的代码手动进行转换Square s = (Square)shape,如果形状是圆形,将会得到java.lang.ClassCastException,因为圆形不是正方形。



1

多态性是在给定类中使用对象的能力,其中组成对象的所有组件都由给定类的子类继承。这意味着,一旦一个类声明了该对象,它下面的所有子类(以及它们的子类,依此类推,直到到达最远/最低的子类)都继承了该对象及其组件(组成)。

请记住,每个类都必须保存在单独的文件中。

以下代码举例说明了多态:

超类:

public class Parent {
    //Define things that all classes share
    String maidenName;
    String familyTree;

    //Give the top class a default method
    public void speak(){
         System.out.println("We are all Parents");
    }
}

父亲,一个子类:

public class Father extends Parent{
    //Can use maidenName and familyTree here
    String name="Joe";
    String called="dad";

    //Give the top class a default method
    public void speak(){
        System.out.println("I am "+name+", the father.");
    }
}

孩子,另一个子类:

public class Child extends Father {
    //Can use maidenName, familyTree, called and name here

    //Give the top class a default method
    public void speak(){
        System.out.println("Hi "+called+". What are we going to do today?");
    }
}

该执行方法引用父类开始:

public class Parenting{
    public static void main(String[] args) {
        Parent parents = new Parent();
        Parent parent = new Father();
        Parent child = new Child();

        parents.speak();
        parent.speak();
        child.speak();
    }
}

请注意,每个类都需要在单独的* .java文件中声明。该代码应编译。还要注意,您可以继续在更下方使用maidenName和familyTree。那就是多态的概念。在这里还探讨了继承的概念,其中可以使用一个类或由子类进一步定义一个类。

希望这会有所帮助并弄清楚。当我找到可用于验证代码的计算机时,我将发布结果。感谢您的耐心配合!


2
请注意,每个孩子都不是父母,因此这种结构是错误的。顶级类别应该是Child(如果您不只是以“ Person”开头),除了Adam以外,其他所有类别都是正确的。您可以将他的parent_id设置为null,因为无法使用任何人类智力来定义创建者。
Yehosef 2014年

1

多态允许相同的例程(函数,方法)作用于不同的类型。

由于许多现有的答案都将子类型与多态性混为一谈,因此这里有三种方法(包括子类型)来实现多态性。

  • 参数(通用)多态性允许例程除常规参数外接受一个或多个类型参数,并在这些类型上运行。
  • 子类型多态性允许例程对其参数的任何子类型起作用。
  • 临时多态通常使用常规重载来授予多态行为,但也可以引用其他多态实现。

也可以看看:

http://wiki.c2.com/?CategoryPolymorphism

https://zh.wikipedia.org/wiki/多态性_(computer_science)


0

在面向对象的语言中,多态性允许通过同一接口处理和处理不同的数据类型。例如,考虑C ++中的继承:类B派生自类A。类型A *的指针(指向类A的指针)可用于处理类A的对象和类B的对象。


0

编码术语中的多态性是指对象可以通过继承等方式以多种类型存在。如果创建一个名为“ Shape”的类来定义对象具有的边数,则可以创建一个继承它的新类,例如“ Square”。 ”。随后,当您创建“ Square”的实例时,可以根据需要将其从“ Shape”投射到“ Square”。


0

多态性使您能够创建一个模块,该模块调用另一个模块,并且具有针对控制流而不是控制流的编译时依赖点。

通过使用多态性,高级模块不依赖于低级模块。两者都依赖于抽象。这有助于我们应用依赖关系反转原理(https://en.wikipedia.org/wiki/Dependency_inversion_principle)。

这是我找到上述定义的地方。大约50分钟后,讲师对以上内容进行了说明。 https://www.youtube.com/watch?v=TMuno5RZNeE


0

什么是多态性?

多态是具有以下能力:

  • 通过在调用专用类型的方法而不是通用类型的方法时只知道通用类型的实例,就可以对该专用类型的实例调用操作:它是动态多态性

  • 定义几种具有保存名称但参数不同的方法:它是静态多态性

首先是历史的定义,也是最重要的。

多态性有什么用?

它允许创建类层次结构的强类型一致性,并执行一些不可思议的事情,例如管理不同类型的对象列表,而不知道它们的类型,但仅是其父类型之一,以及数据绑定。

强弱打字

样品

这是一些形状,如点,线,矩形和圆,它们的Draw()操作不带任何内容,或带一个参数来设置超时以擦除它。

public class Shape
{
 public virtual void Draw()
 {
   DoNothing();
 }
 public virtual void Draw(int timeout)
 {
   DoNothing();
 }
}

public class Point : Shape
{
 int X, Y;
 public override void Draw()
 {
   DrawThePoint();
 }
}

public class Line : Point
{
 int Xend, Yend;
 public override Draw()
 {
   DrawTheLine();
 }
}

public class Rectangle : Line
{
 public override Draw()
 {
   DrawTheRectangle();
 }
}

var shapes = new List<Shape> { new Point(0,0), new Line(0,0,10,10), new rectangle(50,50,100,100) };

foreach ( var shape in shapes )
  shape.Draw();

在这里Shape类和Shape.Draw()方法应标记为抽象。

他们不是为了使理解。

讲解

如果没有多态性,则在解析形状的同时使用abstract-virtual-override时,只有Spahe.Draw()方法被称为CLR,它不知道调用哪种方法。因此它调用我们所作用类型的方法,由于列表声明,此处的类型为Shape。因此,代码根本不执行任何操作。

有了多态性,CLR可以使用所谓的虚拟表来推断我们作用的对象的真实类型。因此,它调用了方法,如果Shape为Point,则在这里调用Shape.Draw()会调用Point.Draw()。因此,代码绘制了形状。

更多阅读

C#-多态性(级别1)

Java中的多态性(级别2)

多态性(C#编程指南)

虚方法表

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.