Каково реальное значение (использование) полиморфизма - PullRequest
25 голосов
/ 17 января 2010

Я новичок в ООП. Хотя я понимаю, что такое полиморфизм, но я не могу его реально использовать. Я могу иметь функции с другим именем. Почему я должен пытаться реализовать полиморфизм в моем приложении.

Ответы [ 10 ]

21 голосов
/ 17 января 2010

Классический ответ: представьте себе базовый класс Shape. Это выставляет GetArea метод. Представьте себе класс Square, класс Rectangle и класс Circle. Вместо того чтобы создавать отдельные методы GetSquareArea, GetRectangleArea и GetCircleArea, вы получаете возможность реализовать только один метод в каждом из производных классов. Вам не нужно знать, какой именно подкласс 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;
}

Здесь важно отметить следующее: вам не нужно знать точный тип используемого вами класса, только базовый тип, и вы получите правильный результат. Это очень полезно и в более сложных системах.

Веселого обучения!

16 голосов
/ 17 января 2010

Вы когда-нибудь добавляли два целых числа с +, а затем добавляли целое число к числу с плавающей запятой с +?

Вы когда-нибудь регистрировали x.toString(), чтобы помочь вам что-то отладить?

Я думаю, вы, вероятно, уже оценили полиморфизм, просто не зная названия.

7 голосов
/ 17 января 2010

В строго типизированном языке полиморфизм важен для того, чтобы иметь список / коллекцию / массив объектов разных типов. Это связано с тем, что списки / массивы сами по себе типизированы и содержат только объекты правильного типа.

Представьте, например, что у нас есть следующее:

// 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();
}

Эти две особенности являются основой того, что делает полиморфизм.

5 голосов
/ 25 февраля 2014

Преимущество полиморфизма заключается в том, что клиентскому коду не нужно заботиться о фактической реализации метода. Взгляните на следующий пример. Здесь 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 голосов
/ 17 января 2010

Полиморфизм является основой объектно-ориентированного программирования. Это означает, что один объект может иметь другой проект. Так как же на объекте может стать другим, это возможно через следующее

  1. Наследование
  2. Переопределение / реализация поведения родительского класса
  3. Привязка объекта времени выполнения

Одним из основных преимуществ этого является реализация переключателя. Допустим, вы кодируете приложение, которое должно общаться с базой данных. И вы случайно определили класс, который выполняет эту операцию с базой данных за вас, и ожидается, что он будет выполнять определенные операции, такие как Add, Delete, Modify. Вы знаете, что база данных может быть реализована разными способами, это может быть взаимодействие с файловой системой или сервером RDBM, таким как MySQL и т. Д. Таким образом, вы, как программист, определите интерфейс, который вы можете использовать, например ...

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

Теперь у вас может быть несколько реализаций, скажем, у нас есть одна для СУБД, а другая для прямой файловой системы

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              
    }
}

Вы можете использовать концепцию полиморфизма во многих местах, например, в одном примере: вы пишете средство для обработки изображений, и вам необходимо поддерживать целый набор изображений, таких как jpg, tif, png и т. Д. Таким образом, ваше приложение определит интерфейс и работа над ним напрямую. И у вас будет некоторое связывание во время выполнения различных реализаций для каждого из jpg, tif, pgn и т. Д.

Еще одно важное применение, если вы используете java, большую часть времени вы будете работать с интерфейсом List, чтобы вы могли использовать ArrayList сегодня или какой-либо другой интерфейс по мере роста вашего приложения или изменения его потребностей.

1 голос
/ 18 января 2010

Одним из наиболее значительных преимуществ, которые вы получаете от полиморфных операций, является способность к расширению. Вы можете использовать те же операции и не изменять существующие интерфейсы и реализации только потому, что столкнулись с необходимостью каких-то новых вещей.

Все, что мы хотим от полиморфизма - это упростить наше дизайнерское решение и сделать наш дизайн более расширяемым и элегантным. Вам также следует обратить внимание на принцип Open-Closed (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).

1 голос
/ 17 января 2010

Полиморфизм позволяет вам писать код, который использует объекты. Затем вы можете позже создать новые классы, которые ваш существующий код может использовать без изменений.

Например, предположим, у вас есть функция Lib2Groc(vehicle), которая направляет транспортное средство из библиотеки в продуктовый магазин. Он должен сказать транспортным средствам повернуть налево, чтобы он мог вызвать TurnLeft() на объекте транспортного средства среди других вещей. Затем, если кто-то позже изобрел новое транспортное средство, такое как судно на воздушной подушке, оно может использоваться Lib2Groc без изменений.

0 голосов
/ 16 октября 2016

Приложения с вкладками

Хорошее приложение для меня - это общие кнопки ( для всех вкладок ) в приложении с вкладками - даже используемый нами браузер реализует полиморфизм, поскольку он не знает вкладку, которую мы используем время компиляции ( внутри кода другими словами ). Его всегда определяют во время выполнения ( прямо сейчас! Когда мы используем браузер.)

0 голосов
/ 17 января 2010

Я думаю, иногда объекты динамически называются.Вы не уверены, будет ли объект треугольником, квадратом и т. Д. В классической форме поли.пример.

Итак, чтобы оставить все это позади, мы просто вызываем функцию производного класса и предполагаем, что будет вызвана функция динамического класса.

Тебе все равно, квадрат это, треугольник или прямоугольник.Вы просто заботитесь о районе.Следовательно, метод getArea будет вызываться в зависимости от переданного динамического объекта.

0 голосов
/ 17 января 2010

Вам не нужен полиморфизм.

Пока не сделаешь.

Тогда это чертовски круто.

Простой ответ, с которым вы будете иметь дело много раз:

Кто-то должен пройти через коллекцию вещей. Допустим, они запрашивают коллекцию типа MySpecializedCollectionOfAwesome. Но вы имели дело со своими экземплярами Awesome как List. Итак, теперь вам нужно будет создать экземпляр MSCOA и заполнить его каждым экземпляром Awesome, который есть в вашем Списке . Сильная боль в заднице, верно?

Ну, если бы они попросили IEnumerable , вы могли бы передать им одну из МНОГИХ коллекций Awesome. Вы можете передать им массив (Awesome []) или List (список ) или наблюдаемую коллекцию Awesome или НИЧЕГО, ЧТО еще вы оставляете своим Awesome, реализующим IEnumerable .

Сила полиморфизма позволяет вам быть безопасным по типу, но при этом быть достаточно гибким, чтобы вы могли использовать экземпляр множеством разных способов, не создавая тонны кода, который специально обрабатывает этот тип или этот тип.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...