多态性的真正意义(用途)是什么?

时间:2010-01-17 05:04:27

标签: oop polymorphism

我是OOP的新手。虽然我理解多态性是什么,但我无法真正使用它。我可以使用不同名称的函数。我为什么要尝试在我的应用程序中实现多态性。

10 个答案:

答案 0 :(得分:21)

经典答案:想象一下基类Shape。它公开了GetArea方法。想象一下Square类和Rectangle类,以及Circle类。您可以在每个派生类中实现一个方法,而不是创建单独的GetSquareAreaGetRectangleAreaGetCircleArea方法。您不必知道您使用的Shape的确切子类,只需调用GetArea即可获得结果,而不管它是哪种具体类型。

看一下这段代码:

#include <iostream>
using namespace std;

class Shape
{
public:
  virtual float GetArea() = 0;
};

class Rectangle : public Shape
{
public:
  Rectangle(float a) { this->a = a; }
  float GetArea() { return a * a; }
private:
  float a;
};

class Circle : public Shape
{
public:
  Circle(float r) { this->r = r; }
  float GetArea() { return 3.14f * r * r; }
private:
  float r;
};

int main()
{
  Shape *a = new Circle(1.0f);
  Shape *b = new Rectangle(1.0f);

  cout << a->GetArea() << endl;
  cout << b->GetArea() << endl;
}

这里要注意的一件重要事情是 - 您不必知道您正在使用的类的确切类型,只需要知道基类型,您将获得正确的结果。这在更复杂的系统中也非常有用。

玩得开心!

答案 1 :(得分:16)

您是否曾使用+添加了两个整数,然后又使用+将整数添加到浮点数?

您是否曾记录x.toString()来帮助您调试某些内容?

我认为你可能已经非常了解多态性,只是不知道这个名字。

答案 2 :(得分:7)

在严格类型的语言中,多态性对于拥有不同类型的对象的列表/集合/数组非常重要。这是因为列表/数组本身的类型只包含正确类型的对象。

想象一下,例如我们有以下内容:

// the following is pseudocode M'kay:
class apple;
class banana;
class kitchenKnife;

apple foo;
banana bar;
kitchenKnife bat;

apple *shoppingList = [foo, bar, bat]; // this is illegal because bar and bat is
                                       // not of type apple.

解决这个问题:

class groceries;
class apple inherits groceries;
class banana inherits groceries;
class kitchenKnife inherits groceries;

apple foo;
banana bar;
kitchenKnife bat;

groceries *shoppingList = [foo, bar, bat]; // this is OK

它还使得处理项目列表更加简单。比如说所有杂货都实现了方法price(),处理这很容易:

int total = 0;
foreach (item in shoppingList) {
    total += item.price();
}

这两个特征是多态性的核心。

答案 3 :(得分:5)

多态性是面向对象编程的基础。这意味着一个对象可以作为另一个项目。那么对象如何成为另一个,它可以通过以下

来实现
  1. 继承
  2. 覆盖/实施父类行为
  3. 运行时对象绑定
  4. 它的一个主要优点是交换机实现。假设您正在编写需要与数据库通信的应用程序。而且您碰巧定义了一个类,它为您执行此数据库操作,并期望执行某些操作,如添加,删除,修改。您知道数据库可以通过多种方式实现,它可以与文件系统或RDBM服务器(如MySQL等)通信。因此,作为程序员,您将定义一个可以使用的接口,例如......

    public interface DBOperation {
        public void addEmployee(Employee newEmployee);
        public void modifyEmployee(int id, Employee newInfo);
        public void deleteEmployee(int id);
    }
    

    现在您可能有多个实现,假设我们有一个用于RDBMS,另一个用于直接文件系统

    public class DBOperation_RDBMS implements DBOperation
        // implements DBOperation above stating that you intend to implement all
        // methods in DBOperation
        public void addEmployee(Employee newEmployee) {
              // here I would get JDBC (Java's Interface to RDBMS) handle
              // add an entry into database table.
        }
        public void modifyEmployee(int id, Employee newInfo) {
              // here I use JDBC handle to modify employee, and id to index to employee
        }
        public void deleteEmployee(int id) {
              // here I would use JDBC handle to delete an entry
        }
    }
    

    让文件系统数据库实现

    public class DBOperation_FileSystem implements DBOperation
        public void addEmployee(Employee newEmployee) {
              // here I would Create a file and add a Employee record in to it
        }
        public void modifyEmployee(int id, Employee newInfo) {
              // here I would open file, search for record and change values
        }
        public void deleteEmployee(int id) {
              // here I search entry by id, and delete the record
        }
    }
    

    让我们看看主要如何在两者之间切换

    public class Main {
        public static void main(String[] args) throws Exception {
              Employee emp = new Employee();
              ... set employee information
    
              DBOperation dboper = null;
              // declare your db operation object, not there is no instance
              // associated with it
    
              if(args[0].equals("use_rdbms")) {
                   dboper = new DBOperation_RDBMS();
                   // here conditionally, i.e when first argument to program is
                   // use_rdbms, we instantiate RDBM implementation and associate
                   // with variable dboper, which delcared as DBOperation.
                   // this is where runtime binding of polymorphism kicks in
                   // JVM is allowing this assignment because DBOperation_RDBMS
                   // has a "is a" relationship with DBOperation.
              } else if(args[0].equals("use_fs")) {
                   dboper = new DBOperation_FileSystem(); 
                   // similarly here conditionally we assign a different instance.
              } else {
                   throw new RuntimeException("Dont know which implemnation to use");
              }
    
              dboper.addEmployee(emp);
              // now dboper is refering to one of the implementation 
              // based on the if conditions above
              // by this point JVM knows dboper variable is associated with 
              // 'a' implemenation, and it will call appropriate method              
        }
    }
    

    你可以在很多地方使用多态概念,一个例子就是:让你编写图像decorer,你需要支持整组图像,如jpg,tif,png等。所以你的应用程序将定义一个界面和直接工作。并且您将为jpg,tif,pgn等每个实现各种实现的运行时绑定。

    另一个重要的用途是,如果您使用的是Java,那么大多数时候您都会使用List接口,这样您就可以在应用程序增长或需求发生变化时立即使用ArrayList或其他界面。

答案 4 :(得分:5)

多态性的优点是客户端代码不需要关心方法的实际实现。 请看下面的例子。 在这里,CarBuilder对ProduceCar()一无所知。一旦给出汽车列表(CarsToProduceList),它将相应地生产所有必需的汽车。

class CarBase
{
    public virtual void ProduceCar()
    {
        Console.WriteLine("don't know how to produce");
    }
}

class CarToyota : CarBase
{
    public override void ProduceCar()
    {
        Console.WriteLine("Producing Toyota Car ");
    }
}

class CarBmw : CarBase
{
    public override void ProduceCar()
    {
        Console.WriteLine("Producing Bmw Car");
    }
}

class CarUnknown : CarBase { }

class CarBuilder
{
    public List<CarBase> CarsToProduceList { get; set; }

    public void ProduceCars()
    {
        if (null != CarsToProduceList)
        {
            foreach (CarBase car in CarsToProduceList)
            {
                car.ProduceCar();// doesn't know how to produce
            }
        }

    }
}

class Program
{
    static void Main(string[] args)
    {
        CarBuilder carbuilder = new CarBuilder();
        carbuilder.CarsToProduceList = new List<CarBase>() { new CarBmw(), new CarToyota(), new CarUnknown() };            
        carbuilder.ProduceCars();
    }
}

答案 5 :(得分:1)

Polymorphism允许您编写使用对象的代码。然后,您可以在以后创建现有代码无需修改即可使用的新类。

例如,假设您有一个功能Lib2Groc(vehicle),可以将车辆从图书馆引导到杂货店。它需要告诉车辆向左转,因此它可以在车辆对象上调用TurnLeft()等。然后,如果有人后来发明了一种新的车辆,比如气垫船,它可以被Lib2Groc使用而无需修改。

答案 6 :(得分:1)

从多态操作中获得的最重要的好处之一是扩展能力。 您可以使用相同的操作,而不是仅仅因为您需要一些新的东西来改变现有的接口和实现。

我们想要的多态性 - 简化了我们的设计决策,使我们的设计更具可扩展性和优雅性。 您还应该注意开放 - 封闭原则(http://en.wikipedia.org/wiki/Open/closed_principle)和SOLID(http://en.wikipedia.org/wiki/Solid_%28Object_Oriented_Design%29),它们可以帮助您理解关键的OO原则。

P.S。我认为你在谈论“动态多态”(http://en.wikipedia.org/wiki/Dynamic_polymorphism),因为有类似“静态多态”(http://en.wikipedia.org/wiki/Template_metaprogramming#Static_polymorphism)的东西。

答案 7 :(得分:0)

您不需要多态性。

直到你。

然后它的friggen很棒。

简单回答你会多次处理:

有人需要经历一系列的事情。假设他们要求MySpecializedCollectionOfAwesome类型的集合。但是你一直在处理你的Awesome实例列表。所以,现在,你将不得不创建一个MSCOA实例,并用你在List&lt; T&gt;中的每个Awesome实例填充它。对接的痛苦,对吧?

好吧,如果他们要求IEnumerable&lt; Awesome&gt;,你就可以把它们交给很多很棒的Awesome。你可以给它们一个数组(Awesome [])或一个List(List&lt; Awesome&gt;)或一个可观察的Awesome或ANYTHING ELSE集合你保持你的Awesome实现IEnumerable&lt; T&gt;。

多态性的强大功能使您可以保持类型安全,但又足够灵活,您可以使用许多不同方式的实例,而无需创建大量专门处理此类型或类型的代码。

答案 8 :(得分:0)

我猜有时会动态调用对象。您不确定对象在经典形状poly中是否为三角形,正方形等。例。

因此,为了抛弃所有这些东西,我们只需调用派生类的函数并假设将调用其中一个动态类。

你不在乎它是一个sqaure,三角形还是矩形。你只关心这个地区。因此,将根据传递的动态对象调用getArea方法。

答案 9 :(得分:0)

标签式应用

一个很好的应用程序是选项卡式应用程序中的通用按钮(所有选项卡) - 即使我们使用它的浏览器也在实现多态性,因为它不知道我们正在使用的选项卡在编译时(代码中的,换句话说)。它始终在运行时确定(现在!当我们使用浏览器时。)