什么是多态性,它有什么作用,以及它如何被使用?
什么是多态性,它有什么作用,以及它如何被使用?
如果你考虑一下这个术语的希腊词根,它应该变得很明显。
因此,多态是编程中的一种能力,可以对不同基础形式(数据类型)提供相同的接口。
例如,在许多语言中,整数和浮点数隐式地具有多态性,因为您可以进行加、减、乘等操作,而不管类型是否不同。它们很少被视为通常术语下的对象。
但是,以同样的方式,像BigDecimal、Rational或Imaginary这样的类也可以提供这些操作,即使它们操作的是不同的数据类型。
经典的例子是Shape类和所有可以从它继承的类(正方形、圆形、十二面体、不规则多边形、splat等)。
通过多态性,每个这些类将具有不同的基础数据。一个点形状只需要两个坐标(当然假设它在二维空间中)。一个圆需要一个中心和半径。正方形或矩形需要两个坐标,分别为左上角和右下角,以及(可能)一个旋转。不规则多边形需要一系列线。
通过让类对其代码和数据负责,可以实现多态性。在这个例子中,每个类都将有自己的Draw()函数,客户端代码只需简单地执行:
shape.Draw()
为了获得任何形状的正确行为,现在的做法是将代码与数据结合在一起,相比之下,旧的做法是代码与数据分离,你需要编写如 drawSquare()
和 drawCircle()
这样的函数。
面向对象、多态和继承都是密切相关的概念,对于了解它们非常重要。在我漫长的职业生涯中,曾经出现过许多所谓的“灵丹妙药”,但是面向对象的范式已经被证明是很好的一个。学习它,理解它,爱上它 - 你会因此受益匪浅 :-)
(a) 我最初把这个写成一个笑话,但它竟然是正确的,因此并不那么好笑。单体苯乙烯由碳和氢组成,C8H8
,而聚苯乙烯则由苯乙烯基团组成,(C8H8)n
。
也许我应该说一个多孔虫是字母 p
的多个实例,尽管现在我不得不解释这个笑话,但它似乎也不好笑。
有时候,你应该趁着自己还没有输得太惨就放弃 :-)
Poly
表示“许多”,Morph
表示“改变或形态”。 - Jo Smo多态性是指当您将对象视为某个通用版本时,但在访问它时,代码确定它的确切类型并调用关联的代码。
这里有一个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,并对它们进行相同的处理,但是当我们访问每个 Vehicle 的“Wheels”属性时,Vehicle 类将执行该代码的委派给相关的子类。这段代码被称为多态,因为在运行时被引用的子类决定要执行的确切代码。希望这能帮助你。Class_Excel
、Class_CSV
,或者使用 Reader
类。无论哪种方式,都需要在某个地方存储某种迭代 if/then/else。 - Oliver Williams来自《理解和应用PHP中的多态性》,感谢Steve Guidetti。
多态性是一个非常简单的概念,却用了一个很长的词来形容它。
在面向对象编程中,多态性描述了一种模式,即不同类在共享相同接口的同时具有不同的功能。
多态性的优点在于处理不同类的代码不需要知道它使用的是哪个类,因为它们都以相同的方式使用。多态性在现实世界中的类比是一个按钮。每个人都知道如何使用按钮:只需施加压力。然而,按钮“做什么”取决于它所连接的东西及其使用的上下文——但结果不影响它的使用方式。如果你的老板让你按一个按钮,那么你已经拥有执行任务所需的所有信息。
在编程世界中,多态性可用于使应用程序更加模块化和可扩展。与其使用混乱的条件语句来描述不同的操作,不如创建可互换的对象,并根据需要进行选择。这是多态性的基本目标。
如果有人对这些人说“Cut”
会发生什么?
因此,上面的表示展示了OOP中的多态性(相同名称,不同行为)。
如果您去面试,面试官要求您在我们坐在同一房间的情况下讲述/展示多态性的实时示例,请说-
答案-门/窗户
想知道为什么吗?
通过门/窗户 - 一个人可以进来,空气可以进来,光线可以进来,雨水可以进来等等。
为了更好地理解并以简单的方式进行说明,我使用了以上的例子。 如果需要代码参考,请参考以上答案。
.foo()
方法,那么它们应该共享一个公共接口。然而,这不是正确的抽象,会导致错误的抽象。一个接口应该定义一个要扮演的角色,这个角色可以有许多不同的实现,但所有的实现都从相同的输入集合中获取数据,并返回相同的输出集合中的内容。对于外科医生、美发师或演员来说,x.cut(...)
的输入都不相同,输出也不相同。 - Matt Klein美国总统采用多态性。怎么做呢?他有很多顾问:
总统不是镀锌或量子物理学的专家。他不知道很多东西。他也不需要知道。他利用多态性方法来治理:
总统所做的就是要求人们给他建议。他的顾问们都会以不同的方式回应,但他们都知道总统的意思是: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 - The President 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都将是实现一个接口的类——我们称之为接口,它只包含一个方法:。但现在我们正在进入具体细节。 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);
}
}
你真正需要知道的就是:
希望能对你有所帮助。如果有任何不明白的地方,请发表评论,我会再次尝试解释。
多态性是指将一个对象类视为其父类的能力。
例如,假设存在一个名为Animal的类和一个继承自Animal的名为Dog的类。多态性是指可以像这样将任何Dog对象视为Animal对象:
Dog* dog = new Dog;
Animal* animal = dog;
多态性:
它是面向对象编程的概念。不同对象对相同消息做出各自不同响应的能力称为多态性。
多态性源于每个类都存在于其自己的命名空间中。类定义内分配的名称不会与任何外部分配的名称冲突。这对于对象数据结构中的实例变量和对象方法都是正确的:
就像 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中通过方法重载和方法覆盖概念实现。
考虑汽车示例以讨论多态性。选择任何品牌,如Ford、Honda、Toyota、BMW、Benz等,它们都是Car类型。
但是,每个品牌都有自己的高级特性和更先进的技术,涉及其移动行为。
现在让我们创建一个基本类型的Car。
Car.java
public class Car {
int price;
String name;
String color;
public void move(){
System.out.println("Basic Car move");
}
}
让我们实现福特汽车的例子。
福特扩展了类型Car以继承其所有成员(属性和方法)。
Ford.java
public class Ford extends Car{
public void move(){
System.out.println("Moving with V engine");
}
}
上述的 Ford 类继承了 Car 类并实现了 move() 方法。尽管通过继承,move 方法已经可用于 Ford,但 Ford 仍然以自己的方式实现了该方法。这称为方法重写。
Honda.java
public class Honda extends Car{
public void move(){
System.out.println("Move with i-VTEC engine");
}
}
就像福特(Ford)一样,本田(Honda)也扩展了汽车类型并以自己的方式实现了移动方法。
方法重写是实现多态性的一个重要特征。使用方法重写,子类型可以改变通过继承可用的方法的工作方式。
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 引用中,move 方法存在于 Car 类型中。因此,编译器在编译过程中通过而没有任何问题。
但是当涉及到运行时执行时,虚拟机会调用子类型对象上的方法的实现。因此,所有的对象都是 Car 类型,但在运行时,执行取决于调用发生的对象。这就是所谓的多态性。
多态是这样的:
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()实例。
我正在浏览另一篇关于完全不同主题的文章…… 然后“多态性”出现了…… 现在我以为我知道什么是多态性了…… 但显然并不是这个美妙的解释方式…… 想把它写下来放在某个地方…… 更好的是我会分享它……
http://www.eioba.com/a/1htn/how-i-explained-rest-to-my-wife
从这部分继续阅读:
..... 多态性。 这是说不同的名词可以被应用相同的动词的极客方式。