ChatGPT解决这个技术问题 Extra ChatGPT

什么是多态性,它的用途是什么,它是如何使用的?

什么是多态性,它的用途是什么,它是如何使用的?

@John:+1 我同意这是一个最有趣的现象。我敢肯定,Unkwntech 并不是唯一一个知识渊博、有能力的人,但在其他人认为是基本词汇方面存在差距。只是表明编程是一个非常广泛的主题。
他可能会使用它,只是不给它一个名字。
@Aamir:我不确定假设拥有 8k 的人会了解所有编程领域的所有基础知识是否合理。我也不认为这表明声誉系统不完善。有人可以通过提出很多好的问题来获得相当大的声誉。我认为我们对这一启示的自然反应只是表明我们(程序员)有一种心胸狭隘的自然倾向(当我们需要在某些特定技术领域非常出色时,这不是一件坏事),并且有其缺点。
你们似乎对编程的看法非常有限。我知道从事嵌入式开发的人根本不了解(或不需要)OO 概念。他们的任务是从代码中榨取性能的每一个原子,仅此而已——他们正在编写的代码永远不会进入对象世界,幸运的是,他们离退休很近,他们不必担心学习新奇的概念,如对象、多态性和超过两个字母的变量名 :-)
你怎么学东西?这个世界上没有人知道 PHP OOP 和设计模式,所以你们所有人都必须在某个时候学习它,在大学里,在这里回答等等。不要谈论某人“不敢已经知道复杂的代码过程”,而是认为他们在这里想要学习它,这是一件好事,也是这个网站的重点。用你的时间帮助他们,因为我相信你过去曾得到过帮助。如果在整个人类历史中,不是分享知识,而是回应“什么?哈!你不知道?..”我们都仍然处于黑暗时代。

M
Maciej Lipinski

如果您考虑该术语的希腊词根,它应该变得显而易见。

Poly = many:多边形 = 多面,聚苯乙烯 = 许多苯乙烯 (a),polyglot = 多种语言,依此类推。

Morph = 变化或形式:形态 = 研究生物形式,Morpheus = 希腊的梦之神,能够采取任何形式。

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

例如,在许多语言中,整数和浮点数是隐式多态的,因为您可以进行加法、减法、乘法等,而不管类型是否不同。通常,它们很少被视为对象。

但是,以同样的方式,像 BigDecimalRationalImaginary 这样的类也可以提供这些操作,即使它们对不同的数据类型进行操作。

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

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

通过让类对其代码和数据负责,您可以实现多态性。在此示例中,每个类都有自己的 Draw() 函数,客户端代码可以简单地执行以下操作:

shape.Draw()

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

这与代码与数据分离的旧方式形成鲜明对比,您将拥有诸如 drawSquare()drawCircle() 之类的函数。

面向对象、多态性和继承都是密切相关的概念,了解它们至关重要。在我漫长的职业生涯中,有许多“灵丹妙药”基本上都以失败告终,但 OO 范式被证明是一个很好的范式。学习它,理解它,爱它——你会很高兴你做到了:-)

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

也许我应该说息肉是字母 p 的多次出现,尽管现在我不得不解释这个笑话,即使这看起来也不好笑。

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


多态性与 OOP 无关,但 OOP 与多态性相关,因为它天生就支持它(假设它是一种体面的 OOP 语言)。查看 FP 以了解多态性的其他示例。
这两行对我有用:Poly = many and Morph = change or form
息肉是息肉(u)s的缩写。 pous 是希腊语。 ;-)
@Shaun,我认为您可能在过于字面/限制性的意义上使用“接口”一词-我的意思是它是一个英语术语,而不是特定于某些任意计算机语言的定义。这并不意味着具有完全相同参数的完全相同的功能,它只是一种以相同方式影响“对象”的方式,而不管它们的底层具体类型如何。这可以包括具有不同参数类型的方法重载以及更纯粹的多态形式。
关于你的编辑:“解释一个笑话就像解剖一只青蛙。你更了解它,但青蛙在这个过程中死了。” - EB白
m
mypetlion

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

这是 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 类将该代码的执行委托给相关的子类。

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

我希望这对你有帮助。


我认为这是一个很好的例子,可以清楚地显示父界面,并且直到对象实例化才需要具体版本,即车辆与汽车
我想说这是最清楚的例子,不过如果你是一名 PHP 程序员,这个链接可能更容易查看 FIRST,然后仍然查看这个链接:code.tutsplus.com/tutorials/…
另外(超出 OP 的范围)请注意,我们将分析限制在已知对象;我们没有传递对象(如导入文件),然后确定它是什么类型(Excel、CSV、YAML、SQL 等)。为此,需要为 Class_ExcelClass_CSV 调用某种工厂类,或者调用 Reader 类。无论哪种方式,某种迭代的 if/then/else 都必须存储在某个地方。
@Antony Gibbs:这是一个非常好的例子(泛型类型列表),对我来说很有意义......否则让每个类都有自己的轮子功能而不从基类继承有什么大不了的?除了列表之外,还有其他对多态有益的概念吗?
A
Ajay Patel

来自 Understanding and Applying Polymorphism in PHP,感谢 Steve Guidetti。

多态性是一个非常简单的概念的长词。多态性描述了面向对象编程中的一种模式,其中类具有不同的功能,同时共享一个公共接口。多态性的美妙之处在于,使用不同类的代码不需要知道它使用的是哪个类,因为它们都以相同的方式使用。多态性的现实世界类比是按钮。每个人都知道如何使用按钮:您只需对其施加压力。然而,按钮的“作用”取决于它所连接的对象和使用它的上下文——但结果并不影响它的使用方式。如果你的老板让你按一个按钮,那么你已经掌握了执行任务所需的所有信息。在编程世界中,多态性用于使应用程序更加模块化和可扩展。您可以创建根据需要选择的可互换对象,而不是描述不同操作过程的凌乱的条件语句。这就是多态性的基本目标。


按钮类比不是更多地与抽象概念相关吗?
@Mantriur:这确实是抄袭,我们有反对的规则:stackoverflow.com/help/referencing但鉴于它现在的分数以及旧帖子在答案删除时免于代表损失的事实,我不确定现在彻底删除它是否会有所改善任何事物。下一个最佳选择是仅代表用户编辑属性,即使我坚信用户有责任在自己的答案中引用来源。
我认为暗示多态性特定于类和/或面向对象的编程是不正确的,因为特设多态性或参数多态性不一定需要类和/或对象。我认为这个答案所说的是子类型(也称为子类型多态性或包含多态性)。
S
Sanchit

如果有人对这些人说 CUT

外科医生 发型师 演员

会发生什么?

外科医生将开始做一个切口。

发型师会开始剪别人的头发。

演员会突然停止在当前场景之外的表演,等待导演指导。

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

如果你要去面试,面试官要求你在我们坐的同一个房间里讲述/展示一个多态性的活生生的例子,比如说 -

答案 - 门/窗

想知道如何?

通过门/窗——人可以进来,空气可以进来,光可以进来,雨可以进来,等等。

为了更好地理解它,我使用了上面的例子。如果您需要参考代码,请按照上面的答案。


我不认为这是一个很好的例子,因为它可能会让没有经验的人认为如果两个类有一个 .foo() 方法,那么它们应该共享一个公共接口。然而,这不是真的,并且会导致不正确的抽象。一个接口应该定义一个要播放的角色,它可能有许多不同的实现,但都从同一组输入中提取并从同一组输出中返回一些东西。外科医生、造型师或演员的 x.cut(...) 输入不同,输出也不同。
B
BenKoshy

类推简单

美国总统使用多态性。如何?嗯,他有很多顾问:

军事顾问 法律顾问 核物理学家(作为顾问)等

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

总统不是锌涂层或量子物理学方面的专家。他不知道很多事情。但他确实知道如何治理国家。

代码有点类似:关注点和责任应该与相关的类/人分开。这使得维护代码更容易,尤其是在您进行更改时。变化是不可避免的。当事情发生变化时,您不想破坏应用程序的其他部分。总统应该坚持管理国家,而不是深入专业领域的本质:

为什么总统知道所有这些具体事情是个坏主意?

如果总统要具体告诉人们该做什么,那就意味着总统需要确切地知道该做什么。如果总统需要自己知道具体的事情,那就意味着当你需要做出改变时,你需要在两个地方做出改变,而不仅仅是一个地方。

例如,如果 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 :))

我真的希望它可以帮助你。如果您有任何不明白的地方发表评论,我会再试一次。


很棒的例子!谢谢。
非常有趣的类比。谢谢你。
@TTT 因为(1)每次您有新顾问时,您都必须更改总统班-您不想进行 x2 更改。只有一个。 (2) 其次,如果您必须更换现有的顾问,那么您可能必须返回并更改总统课程中的这三个电话中的一个 - 您真的只想进行一项更改,而不是两次。 (3) 如果您有三个单独的电话,那么您将不得不在总统类中询问:if healthAdvisor? then do this:if petraus then do that etc. 这种模式需要重复,这是不必要且复杂的。见上面的编辑。
@TTT 是的,你是对的。但我必须慢慢地向读者介绍这个概念,否则他们将无法理解。我添加了进一步的更改。请告知是否需要澄清
@TTT 基类与接口是程序员在进行多态性时必须做出的设计决策。有关详细信息,请参见此处:stackoverflow.com/questions/56867/interface-vs-base-class
T
Tom Dalling

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

例如,假设有一个名为 Animal 的类,以及一个继承自 Animal 的名为 Dog 的类。多态性是将任何 Dog 对象视为 Animal 对象的能力,如下所示:

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

我想知道这与@Ajay Patel 给出的(流行的)解释有什么关系classes have different functionality while sharing a common interface
@BornToCode 父类是/提供该公共接口。
多态性不需要子类型化。
T
Tony Stark

多态性:

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

多态性源于每个类都存在于自己的命名空间中。在类定义中分配的名称不会与在它之外的任何地方分配的名称冲突。对象的数据结构中的实例变量和对象的方法都是如此:

正如 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 示例。以福特,本田,丰田,宝马,奔驰等任何品牌为例,一切都是Car类型。

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

现在让我们创建一个基本类型 Car

汽车.java

public class Car {

    int price;
    String name;
    String color;

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

}

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

Ford 扩展了 Car 类型以继承它的所有成员(属性和方法)。

福特.java

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

上面的 Ford 类扩展了 Car 类,还实现了 move() 方法。尽管移动方法已经通过继承提供给福特,但福特仍然以自己的方式实现了该方法。这称为方法覆盖。

本田.java

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

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

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

多态Example.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 类的主方法中,我创建了三个对象——汽车、福特和本田。这三个对象都由 Car 类型引用。

请注意这里的重要一点,超类类型可以引用对象的子类类型,但反之亦然。原因是超类的所有成员都可用于子类使用继承,并且在编译期间,编译器会尝试评估我们正在使用的引用类型是否具有他试图访问的方法。

因此,对于 PolymorphismExample 中的引用 car、f 和 h,move 方法存在于 Car 类型中。因此,编译器通过编译过程没有任何问题。

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

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


重载概念与继承和多态无关。
@srk 方法重载是实现多态性的一种方法。它通常被归类为静态或临时多态性。 wiki.c2.com/?CategoryPolymorphism
J
JesperE

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

面向对象编程中的多态性

类型多态性

编辑:修复断开的链接。


“A 类型的对象表现得像 B 类型的对象的能力” - 这不是准确的定义。我会说它更像是能够将 A 类型的对象视为 B 类型的对象。
是的。也许这是一个更好的措辞。
为了完整起见,许多语言通过鸭子类型实现多态性,例如 Python。
我想知道这与@Ajay Patel 给出的(流行的)解释有什么关系classes have different functionality while sharing a common interface
V
Vinko Vrsalovic

多态是这样的:

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() 实例


这特别是亚型多态性。
@vinko-vrsalovic:美国农村的软件开发是什么样的?
A
Abe Miessler

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

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

上面有很多例子表明了这一点,但我觉得这是一个很好的简洁答案。


这是子类型,它只是一种多态性。
@ShaunLuttin 你能给我指点任何资源来了解更多关于其他类型的多态性吗?
除了“子类型多态性”之外,还有“特殊多态性”和“参数多态性”。
K
Kcats Wolfrevo

(我正在浏览另一篇关于完全不同的文章.. 多态性突然出现......现在我以为我知道多态性是什么......但显然不是以这种美丽的方式解释......想把它写下来......更好的还是会分享它...)

http://www.eioba.com/a/1htn/how-i-explained-rest-to-my-wife

从这部分继续阅读:

.....多态性。这是一种怪异的说法,不同的名词可以使用相同的动词。


S
Stewart

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

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

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

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


t
tzup

术语多态性来自:

聚 = 许多

态射=改变的能力

在编程中,多态性是一种“技术”,它可以让您“看待”一个对象不仅仅是一种类型的事物。例如:

一个学生对象也是一个人对象。如果您“看”(即投射)学生,您可能会要求提供学生证。你不能总是对一个人这样做,对吧? (一个人不一定是学生,因此可能没有学生证)。但是,一个人可能有一个名字。一个学生也是。

底线,从不同的“角度”“看”同一个物体可以给你不同的“视角”(即不同的属性或方法)

所以这种技术可以让你构建可以从不同角度“观察”的东西。

为什么我们使用多态性?对于初学者...抽象。此时应该有足够的信息:)


B
Boris Pavlović

让我们打个比方。对于一个给定的音乐剧本,每个演奏它的音乐家都会在解释中给出自己的感受。

音乐家可以用接口抽象,音乐家所属的流派可以是一个抽象类,它定义了一些全局的解释规则,每个演奏的音乐家都可以用一个具体的类来建模。

如果您是音乐作品的听众,您会参考脚本,例如巴赫的“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());
}

AnnHallowayVictorBorga 感觉它们应该是对象而不是类 - 您的示例使用 eg 会更好读。 public class Pianist implements MusicianvictorBorge = new Pianist(); 等。
C
Community

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

Polymorphism in c++

希望能帮助到你。提取物...

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

Type1 x;
Type2 y;

f(x);
f(y);

在这里, f() 将执行一些操作,并被赋予值 x 和 y 作为输入。要成为多态,f() 必须能够对至少两种不同类型(例如 int 和 double)的值进行操作,找到并执行适合类型的代码。

(在 Polymorphism in c++ 继续)


s
sjith

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


R
Rohit

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


M
Mohammad

多态性是对象具有多种形式的能力。 OOP 中最常见的多态性使用发生在使用父类引用来引用子类对象时。在这个用 Java 编写的示例中,我们有三种类型的车辆。我们创建三个不同的对象并尝试运行它们的轮子方法:

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://i.stack.imgur.com/ZWtxV.jpg

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


是的,但你没有解释多态性有什么好处。显然有一个更短的代码,您可以在其中删除 Vehicle 类,它仍然可以工作(当然,使用不同的对象声明)。
我没有解释,因为提出问题的人没有询问好处。他问:“什么是多态性,它是干什么用的,它是如何使用的?”。关于代码,如果您可以做得更好,请发布您的答案。所以,我们的社区可以使用它。谢谢你的评论。
抱歉,不想显得粗鲁,其他人也没有解释。至少你费心输入代码。不管怎样,他问它是干什么用的,但是这个页面上的例子都没有解释它是干什么用的。你们都只是提出了一种复杂的方法来获得与此相同的结果:s28.postimg.org/jq8vl6031/Poly.jpg并且没有人愿意解释为什么要使用多态性,它的好处或目的是什么,如果不使用它就不能做?我在此页面上看到的只是使用楼梯而不是电梯爬上公寓的提议。
..没有注意到一个人携带的旗杆太大而无法容纳电梯。我不知道如何发布代码,所以我帮不上什么忙...
A
Alex Basson

多态性是程序员编写同名方法的能力,这些方法根据这些对象的需要为不同类型的对象做不同的事情。例如,如果您正在开发一个名为 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

其他一些答案似乎暗示多态性仅与继承结合使用。例如,可能 FractionComplexNumber 都实现了一个名为 Number 的抽象类,它有一个方法 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() 方法,即使开发人员无法提前知道用户将选择分数还是复数。


那不是多态性。那是两个具有相同名称的方法的类。它们需要通过称为“可显示”或类似名称的基类或接口链接,然后其他方法只需关心对象是“可显示”类型而不是复杂或分数类型。
我一直认为多态是“两个类具有相同名称的方法”。事实上,引用 Stephan Kochan(我无耻地抄袭了这个分数/复数示例)的话,“在不同的类之间共享相同的方法名称的能力被称为多态性。” (来自 Programming_In_Objective-C)他没有提到任何需要通过基类链接类。也许不同的语言会有所不同,我真的不知道。
即使这个辩护是从一本出版的书中引用的,我仍然认为它是不正确的。特别是因为它似乎与其他语言冲突,多态性的语言不可知论定义。虽然最终结果与多态性相同,但我认为,相反,动态类型允许程序员能够在其他类似命名的方法中推动方法的正确实现。
S
Shourob Datta

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

考虑一个人 X。

他只是一个人,但他的行为却是一样多的。你可能会问如何:

他是他母亲的儿子。朋友对他的朋友。一个弟弟对他妹妹。


Z
Zack Braksa

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

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


H
HASSAN MD TAREQ

多态性:

根据类的实例不同执行,而不是引用变量的类型。

接口类型引用变量可以引用实现该接口的任何类实例。


佚名

什么是多态性?

多态性是以下能力:

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

定义几个具有保存名称但具有不同参数的方法:这是静态多态性。

第一个如果是历史定义,也是最重要的。

多态性是做什么用的?

它允许创建类层次结构的强类型一致性,并做一些神奇的事情,比如管理不同类型的对象列表,而不知道它们的类型,但只知道它们的父类型之一,以及数据绑定。

Strong and weak typing

样本

这里有一些形状,比如点、线、矩形和圆形,它们的 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() 方法应该被标记为抽象的。

他们不是为了让人理解。

解释

没有多态性,使用抽象虚拟覆盖,在解析形状时,只有 Spahe.Draw() 方法被调用,因为 CLR 不知道调用什么方法。所以它调用了我们作用的类型的方法,这里的类型是 Shape 因为列表声明。所以代码什么都不做。

借助多态性,CLR 能够infer使用所谓的虚拟表来处理我们所操作的对象的真实类型。所以它调用 good 方法,这里调用 Shape.Draw() 如果 Shape 是 Point 调用 Point.Draw()。所以代码绘制形状。

更多阅读

C# - Polymorphism (Level 1)

Polymorphism in Java (Level 2)

Polymorphism (C# Programming Guide)

Virtual method table


M
Midimistro

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

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

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

超类:

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?");
    }
}

执行方法,引用Parent类启动:

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 更远。这就是多态性的概念。这里还探讨了继承的概念,其中一个类可以使用或由子类进一步定义。

希望这会有所帮助并说明清楚。当我找到可以用来验证代码的计算机时,我会发布结果。谢谢你的耐心!


请注意,每个孩子都不是父母,因此这种结构是错误的。顶级课程应该是 Child(如果您不只是从“Person”开始),除了 Adam 之外,这始终是正确的。您可以将他的 parent_id 设置为 null,因为无法使用任何人类智力构造来定义 Creator。
S
Shaun Luttin

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

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

参数(通用)多态性允许例程接受一个或多个类型参数,除了普通参数,并在这些类型上运行自己。

子类型多态性允许例程对其参数的任何子类型进行操作。

Ad hoc 多态性通常使用例程重载来授予多态性行为,但也可以引用其他多态性实现。

也可以看看:

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

https://en.wikipedia.org/wiki/Polymorphism_(computer_science)


E
Eran Rehavi

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


B
Brian Scott

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


R
Raghav Navada

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

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

这是我找到上述定义的地方。在视频播放大约 50 分钟后,讲师解释了上述内容。 https://www.youtube.com/watch?v=TMuno5RZNeE