Что такое полиморфизм, для чего он нужен и как он используется? - PullRequest
515 голосов
/ 23 июня 2009

Что такое полиморфизм, для чего он нужен и как он используется?

Ответы [ 27 ]

509 голосов
/ 23 июня 2009

Если вы думаете о греческих корнях термина, это должно стать очевидным.

  • Поли = много: многоугольник = многогранник, полистирол = много стиролов (а) , полиглот = много языков и т. Д.
  • Морф = изменение или форма: морфология = изучение биологической формы, Морфеус = греческий бог снов, способный принимать любую форму.

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

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

Но таким же образом класс, такой как BigDecimal или Rational или Imaginary, также может предоставлять эти операции, даже если они работают с различными типами данных.

Классическим примером является класс Shape и все классы, которые могут наследовать от него (квадрат, круг, додекаэдр, неправильный многоугольник, сплат и т. Д.).

При полиморфизме каждый из этих классов будет иметь разные базовые данные. Точечной форме нужны только две координаты (конечно, при условии, что она находится в двумерном пространстве). Круг нуждается в центре и радиусе. Квадрату или прямоугольнику нужны две координаты для верхнего левого и нижнего правого углов и (возможно) вращения. Нерегулярный многоугольник нуждается в серии линий.

Делая класс ответственным за его код и данные, вы можете достичь полиморфизма. В этом примере каждый класс будет иметь свою собственную функцию Draw(), а клиентский код может просто выполнить:

shape.Draw()

чтобы получить правильное поведение для любой фигуры.

Это в отличие от старого способа делать вещи, в которых код был отделен от данных, и у вас были бы такие функции, как drawSquare() и drawCircle().

Объектная ориентация, полиморфизм и наследование - все это тесно связанные понятия, и их важно знать. В течение моей долгой карьеры было много «серебряных пуль», которые в основном просто кончились, но парадигма ОО оказалась хорошей. Изучите это, поймите это, любите это - Вы будете рады, что сделали: -)


(а) Первоначально я написал это как шутку, но она оказалась правильной и, следовательно, не такой уж смешной. Мономер стирола, как оказалось, сделан из углерода и водорода, C<sub>8</sub>H<sub>8</sub>, и полистирол сделан из групп этого (C<sub>8</sub>H<sub>8</sub>)<sub>n</sub>.

Возможно, мне следовало сказать, что полип был во многих случаях в письме p, хотя теперь, когда мне пришлось объяснять шутку, даже это тоже не кажется смешным.

Иногда вам нужно просто выйти, пока вы позади: -)

231 голосов
/ 24 июня 2010

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

Вот пример на 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 передает выполнение этого кода соответствующему подклассу.

Этот код называется полиморфным, поскольку точный код, который выполняется, определяется подклассом, на который ссылаются во время выполнения.

Надеюсь, это вам поможет.

192 голосов
/ 04 ноября 2011

С Понимание и применение полиморфизма в PHP , спасибо Стиву Гидетти.

Полиморфизм - это длинное слово для очень простого понятия.

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

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

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

53 голосов
/ 15 ноября 2014

Если кто-нибудь скажет "ВЫРЕЗАТЬ" этим людям

  1. Хирург
  2. Стилист
  3. Актер

Что будет?

  • Хирург начнет делать надрез.
  • Парикмахер начнет стричь кого-то.
  • Актер внезапно прекратил бы действовать за пределами текущей сцены, в ожидании директивных указаний.

Итак, приведенное выше представление показывает, что такое полиморфизм (то же имя, другое поведение) в ООП.

Если вы идете на собеседование, и интервьюер попросит вас рассказать / показать живой пример полиморфизма в той же комнате, где мы сидим, скажем -

Ответ - Дверь / Окна

Хотите знать, как?

Через Дверь / Окно - человек может прийти, воздух может прийти, свет может прийти, дождь может прийти и т. Д.

Чтобы понять это лучше и проще, я использовал приведенный выше пример .. Если вам нужна ссылка для кода, следуйте приведенным выше ответам.

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

Простое объяснение по аналогии

Президент Соединенных Штатов использует полиморфизм. Как? Ну, у него много советников:

  1. Военные советники
  2. Юрисконсульты
  3. Физики-ядерщики (в качестве советников)
  4. Медицинские консультанты
  5. и т. Д. И т. Д.

Каждый должен нести ответственность только за одну вещь: Пример:

Президент не является специалистом по цинкованию или квантовой физике. Он не знает многих вещей - но он знает только одно: как управлять страной.

То же самое с кодом: проблемы и обязанности должны быть разделены между соответствующими классами / людьми. В противном случае, если бы президент знал буквально все на свете - всю Википедию Представьте, что в вашем коде есть вся википедия: поддерживать ее было бы кошмаром.

Почему президенту плохо знать все эти специфические вещи?

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

Например, если 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 ()».

Что вы не хотите: T

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: ))

Я действительно надеюсь, что это поможет вам. Если вы ничего не понимаете, оставьте комментарий, и я попробую еще раз.

23 голосов
/ 23 июня 2009

Полиморфизм - это способность обрабатывать класс объекта как родительский класс.

Например, предположим, что есть класс с именем Animal и класс с именем Dog, который наследуется от Animal. Полиморфизм - это способность рассматривать любой объект Dog как объект Animal следующим образом:

Dog* dog = new Dog;
Animal* animal = dog;
22 голосов
/ 05 февраля 2013

Полиморфизм:

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

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

  • Как поля структуры 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.java тысяча сорок-девять
public class Car {

    int price;
    String name;
    String color;

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

}

Давайте реализуем пример Ford Car.

Ford расширяет тип Car, чтобы наследовать все его члены (свойства и методы).

Ford.java

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

Приведенный выше класс Ford расширяет класс Car, а также реализует метод 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 я создал три объекта - Автомобиль, Форд и Хонда. Все три объекта относятся к типу автомобиля.

Обратите внимание на важный момент: тип суперкласса может ссылаться на тип объекта подкласса, но обратный вариант невозможен. Причина в том, что все члены суперкласса доступны для подкласса с использованием наследования, и во время компиляции компилятор пытается оценить, имеет ли используемый нами ссылочный тип метод, к которому он пытается получить доступ.

Итак, дляВ ссылках car, f и h в PolymorphismExample метод move существует из типа Car. Таким образом, компилятор без проблем проходит процесс компиляции.

Но когда дело доходит до выполнения во время выполнения, виртуальная машина вызывает методы объектов, которые являются подтипами. Таким образом, метод move () вызывается из их соответствующих реализаций.

Итак, все объекты относятся к типу Car, но во время выполнения выполнение зависит от объекта, для которого происходит вызов. Это называется полиморфизмом.

12 голосов
/ 23 июня 2009

Обычно это относится к способности объекта типа A вести себя как объект типа B. В объектно-ориентированном программировании это обычно достигается наследованием. Некоторые ссылки на Википедию, чтобы прочитать больше:

РЕДАКТИРОВАТЬ: исправлены неработающие ссылки.

9 голосов
/ 24 июня 2010

Полиморфизм таков:

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 () для каждого типа чашки

8 голосов
/ 18 октября 2012

Я знаю, что это старый вопрос с множеством хороших ответов, но я хотел бы включить ответ в одном предложении:

Обработка производного типа, как если бы он был базовым типом.

Есть много примеров выше, которые показывают это в действии, но я чувствую, что это хороший краткий ответ.

...