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

26 oop polymorphism

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

Mar*_*ski 22

经典答案:想象一下基类Shape.它暴露了一种GetArea方法.想象一个Square类,一个Rectangle类和一个Circle类.而不是创建独立的GetSquareArea,GetRectangleAreaGetCircleArea方法,你能实现在每个派生类中只有一个方法.您不必知道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;
}
Run Code Online (Sandbox Code Playgroud)

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

玩得开心学习!


Ken*_*Ken 16

你有没有添加两个整数+,然后添加一个整数到一个浮点数+

你有没有登录过来x.toString()帮助你调试一些东西?

我想你可能已经欣赏了多态性,只是不知道这个名字.


sle*_*man 8

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

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

// 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.
Run Code Online (Sandbox Code Playgroud)

要解决这个问题:

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
Run Code Online (Sandbox Code Playgroud)

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

int total = 0;
foreach (item in shoppingList) {
    total += item.price();
}
Run Code Online (Sandbox Code Playgroud)

这两个特性是多态性的核心.


chi*_*aya 5

多态性是面向对象编程的基础.这意味着一个对象可以作为另一个项目.那么对象如何成为其他对象,可以通过以下方式实现

  1. 遗产
  2. 覆盖/实现父类行为
  3. 运行时对象绑定

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

public interface DBOperation {
    public void addEmployee(Employee newEmployee);
    public void modifyEmployee(int id, Employee newInfo);
    public void deleteEmployee(int id);
}
Run Code Online (Sandbox Code Playgroud)

现在您可能有多个实现,假设我们有一个用于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
    }
}
Run Code Online (Sandbox Code Playgroud)

让我们有文件系统数据库实现

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
    }
}
Run Code Online (Sandbox Code Playgroud)

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

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              
    }
}
Run Code Online (Sandbox Code Playgroud)

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

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


Lit*_*Bit 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();
    }
}
Run Code Online (Sandbox Code Playgroud)