尝试尽可能简单地描述多态性

多态如何以易于理解的方式来描述?

我们可以在互联网和书籍上find很多关于这个主题的信息,比如Type多态 。 但是,我们尽可能简单地做到这一点。

这是我从一个类似的问题的答案 。 下面是伪C#/ Java中的一个多态的例子:

class Animal { abstract string MakeNoise (); } class Cat : Animal { string MakeNoise () { return "Meow"; } } class Dog : Animal { string MakeNoise () { return "Bark"; } } Main () { Animal animal = Zoo.GetAnimal (); Console.WriteLine (animal.MakeNoise ()); } 

Main()方法不知道动物的types,取决于MakeNoise()方法的特定实现的行为。

两个对象以不同的行为来回应相同的消息; 发件人不必关心。

每一个可以用一个简单的popup式盖子打开相同的方式。
作为一个人,你知道你可以打开()任何你可以find。

打开时,并不是所有jar头的行为都是一样的。
有些含有坚果,有些含有popup的假蛇。
结果取决于can的types,can是CanOfNuts还是CanOfSnakes,但是这对你打开它没有任何影响。 你只知道你可以打开任何jar头,并会得到某种结果,这个结果是根据你打开jar头的types决定的。

pUnlabledCan->打开(); //可能会给坚果,可能会给蛇。 直到我们称之为我们才知道

Open()有一个通用的返回types“Contents”(或者我们可能决定没有返回types),所以打开总是有相同的函数签名。

你是人,是用户/呼叫者。
Open()是虚拟/多态的function。
“Can”是抽象基类。
CanOfNuts和CanOfSnakes是“Can”类的多态孩子。
每一个Can都可以被打开,但是具体什么以及它返回什么特定的内容是由什么样的可以定义的。
当你看到pUnlabledCan的时候,你所知道的是你可以打开()它,它会返回内容。 任何其他的行为(比如你脸上的蛇)都是由特定的Can决定的。

多态的最简单的描述是它是减lessif / switch语句的一种方法

它还具有允许在不修改现有类的情况下扩展if / switch语句(或其他人的语句)的好处。

例如,考虑.NET中的Stream类。 没有多态性,它将是一个单一的大型类,其中每个方法实现一个switch语句如下所示:

 public class Stream { public int Read(byte[] buffer, int offset, int count) { if (this.mode == "file") { // behave like a file stream } else if (this.mode == "network") { // behave like a network stream } else // etc. } } 

相反,我们允许运行时通过自动select基于具体types( FileStreamNetworkStream )的实现来更有效地为我们进行切换,例如

 public class FileStream : Stream { public override int Read(byte[] buffer, int offset, int count) { // behave like a file stream } } public class NetworkStream : Stream { public override int Read(byte[] buffer, int offset, int count) { // behave like a network stream } } 

保利:很多
形态主义:forms/forms

演员与angular色(或angular色)

苹果和橘子都是水果。 水果可以吃。 因此,苹果和橘子都可以吃。

踢球者? 你以不同的方式吃东西 你剥橘子,但不是苹果。

所以执行有所不同,但最终的结果是一样的, 你吃的水果

如果它像鸭子一样走路,像鸭子一样嘎嘎叫,那么你可以在任何需要鸭子的地方把它当作鸭子来对待。

实际上这是一个更好的文章

多态性允许对象“看”相同,但行为以不同的方式。 通常的例子是用Speak()方法取动物基类,一个狗子类会发出一个树皮,而一个猪子类会发出一个oink。

大多数人使用的5秒短的答案,所以其他开发人员可以得到他们的头多态是超载和重写

相同的语法,不同的语义。

最简单的描述方式:一个动词,可以适用于多种对象。

正如希勒尔所说的,其他一切只是评论。

多态性是通过依靠一个共同的“父母”的知识来抽象地处理事物(认为像动物一样是像狗和猫的父母那样的动物)。

例如,所有的动物都可以呼吸氧气,虽然他们每个人都可以做不同的事情,但您可以devise一种能够为动物提供氧气的设施,以便呼吸,支持狗和猫。

另外,即使Animal是一个“抽象的”标识符(没有真正的“动物”的东西,只有动物的types),你可以做到这一点。

多态性是将多于一种types的值存储在单一types的位置中。

请注意,在我写这篇文章的时候,其他大部分的答案都是描述dynamic调度,而不是多态。

dynamic调度需要多态性,但反过来却是不正确的。 可以想象一种非常类似于Java或C#但是其System.Object没有成员的语言; 在做任何有价值的事情之前,types转换都是必要的。 在这个概念性语言中,将会有多态性,但不一定是虚拟方法,或者其他dynamic调度机制。

dynamic调度是相关的但是独特的概念,在大多数其他的答案中已经描述得很好。 然而,它通常在面向对象语言中工作的方式(select基于第一个('this'或'Self'参数types的函数)并不是它可以工作的唯一方式。 多个分派也是可能的,其中select应用于所有参数的types。

同样,超负荷分辨率和多次调度是相互精确的类似; 重载parsing是应用于静态types的多重分派,而多重分派则是应用于存储在多态位置的运行时types的重载parsing。

多态性是把世界划分为基于共同属性的盒子,并且当你只想使用这些共同的属性时,把盒子中的项目互相处理为可互换的。

多态性是通过build立一个共享的身份然后利用它的方式来对待不同事物的能力,就好像它们是同一事物一样

当同样的方法适用于多个类时,多态性就是你所得到的。 例如,一个string和一个列表可能有“反向”的方法。 两种方法都有相同的名称(“反向”)。 两种方法都做了非常相似的操作(反转所有字符或颠倒列表中元素的顺序)。 但是每个“反向”方法的实现与其类是不同的和具体的。 (换句话说,String像string一样反转,List像列表一样反转。)

用一个比喻,你可以说一个法国厨师或一个日本厨师“做晚餐”。 每个人都会以自己特有的方式表演“做晚饭”。

实际的结果是,你可以创build一个“反转引擎”,它接受一个对象并调用“反转”。 只要对象有一个Reverse方法,你的Reversing Engine就可以工作。

要扩大厨师的比喻,你可以build立一个“服务员”,告诉厨师“做晚餐”。 Waiterbot不需要知道什么types的晚餐将被做。 它甚至不必确定它正在与厨师交谈。 重要的是,“厨师”(或消防员,或自动售货机,或宠物食品加工机)知道该做什么,当被告知“做晚餐”时。

作为程序员,你购买的是less量代码,无论是types安全还是后期绑定。 例如,下面是一个types安全和早期绑定的例子(用我正在编写的类C语言):

 class BankAccount { void SubtractMonthlyFee } class CheckingAccount : BankAccount {} class SavingsAccount : BankAccount {} AssessFee(BankAccount acct) { // This will work for any class derived from // BankAccount; even classes that don't exist yet acct.SubtractMonthlyFee } main() { CheckingAccount chkAcct; SavingsAccount saveAcct; // both lines will compile, because both accounts // derive from "BankAccount". If you try to pass in // an object that doesn't, it won't compile, EVEN // if the object has a "SubtractMonthlyFee" method. AssessFee(chkAcct); AssessFee(saveAcct); } 

这里有一个没有types安全的例子,但是后期绑定:

 class DatabaseConnection { void ReleaseResources } class FileHandle { void ReleaseResources } FreeMemory(Object obj) { // This will work for any class that has a // "ReleaseResources" method (assuming all // classes are ultimately derived from Object. obj.ReleaseResources } main() { DatabaseConnection dbConn; FileHandle fh; // You can pass in anything at all and it will // compile just fine. But if you pass in an // object that doesn't have a "ReleaseResources" // method you'll get a run-time error. FreeMemory(dbConn); FreeMemory(fh); FreeMemory(acct); //FAIL! (but not until run-time) } 

对于一个很好的例子,看一下.NET的ToString()方法。 所有的类都有它,因为所有的类都是从Object类派生的。 但是每个类都可以以对自己有意义的方式实现ToString()。

编辑:简单!=短,恕我直言

多态性是语言function,允许高级algorithm代码在多种types的数据上保持不变。

这是通过确保操作调用每个数据types的正确实现来完成的。 即使在OOP的上下文中(根据这个问题的标签),这个“正确的实现”可能在编译时或运行时(如果你的语言同时支持的话)解决。 在一些像C ++这样的语言中,编译器为运行时多态(即虚拟调度)提供了对OOP特有的支持,而其他types的多态也可以对不是对象的数据types(即不是structclass实例,可能是像intdouble内置types)。

(C ++支持多态的types在我的答案中被列出和对比: c ++中的多态 – 即使你编程其他语言也是有启发意义的)

我尝试和想到的方式是看起来相同,但可以有不同的function取决于实例。 所以你可以有一个types

 interface IJobLoader 

但取决于它如何使用可以有不同的function,而仍然看起来相同。 你可能有BatchJobLoader,NightlyJobLoader等实例

也许我走了。

术语多态也可以用于重载函数。 例如,

 string MyFunc(ClassA anA); string MyFunc(ClassB aB); 

是多态的非面向对象的例子。

对象必须以不同的方式回应相同的信息的能力。

例如,在Smalltalk,Ruby,Objective-C等语言中,只需发送消息,他们就会响应。

  dao = XmlDao.createNewInstance() #obj 1 dao.save( data ) dao = RdbDao.createNewnewInstance() #obj 2 dao.save( data ) 

在这个例子中,两个不同的对象以不同的方式回应相同的消息:“createNewInstance()和save(obj)”

他们以不同的方式行事,以相同的信息。 在上述语言中,这些类可能甚至不在同一个类层次结构中,只要他们对消息作出响应即可。

在诸如Java,C ++,C#等语言中,为了将对象分配给对象引用,它们必须通过实现接口或通过作为普通类的子类来共享相同的types层次结构。

容易..简单。

多态是迄今为止,面向对象编程最重要和相关的特征。

这是一种对待不同事物的方式,可以以同样的方式做一些类似的事情,而不必关心他们如何做。

比方说,你有一系列不同种类的汽车,如汽车,卡车,滑板,飞机等等,他们都可以停下来,但是每辆车都以不同的方式停下来。 有些车辆可能需要减档,有些车辆可能会停下来。 Polymophism让你做到这一点

 foreach (Vehicle v in Game.Vehicles) { v.Stop(); } 

停止的方式被推迟到不同的车辆,所以你的程序不必关心它。

这只是让老年人冷眼看新代码的一种方式。 你写一些应用程序接受一些“形状”接口与其他人必须实现的方法(例如 – getArea)。 如果有人想出一个新的方法来实现这个接口,你的旧代码可以通过getArea方法调用这个新代码。

某种types的物体(例如汽车)在types层次结构中的某一点像另一种types的车辆(例如车辆)那样通常提示共同的祖先(例如,汽车是车辆的子types) 。

多态是面向对象的解决scheme,将function传递给另一个function。 在C你可以做

  void h() { float x=3.0; printf("%f", x); } void k() { int y=5; printf("%i", y); } void g(void (*f)()) { f(); } g(h); // output 3.0 g(k); // output 5 

在C中,如果函数依赖于其他参数,则会变得复杂。 如果函数h和k取决于不同types的参数,则遇到麻烦,必须使用强制转换。 您必须将这些参数存储在数据结构中,并将指向该数据结构的指针传递给将其传递给h或k的g。 h和k将指针转换为指向正确结构的指针并解包数据。 非常混乱,非常不安全,因为可能的铸造错误:

  void h(void *a) { float* x=(float*)a; printf("%f",*x); } void k(void *a) { int* y=(int*)a; printf("%i",*y); } void g(void (*f)(void *a),void *a) { f(a); } float x=3.0; int y=5; g(h,&x); // output x g(k,&y); // output y 

所以他们发明了多态性。 h和k被提升为类,实际函数被提升为方法,参数是相应类h或k的成员variables。 不是传递函数,而是传递包含所需函数的类的实例。 该实例包含自己的参数。

 class Base { virtual public void call()=0; } class H : public Base { float x; public void call() { printf("%f",x);} } h; class K : public Base { int y; public void call() { printf("%i",y);} } k; void g(Base &f) { f.call(); }; hx=3.0; ky=5; g(h); // output hx g(k); // output kx