Що таке поліморфізм, для чого він призначений і як його застосовують?


564

Що таке поліморфізм, для чого він призначений і як його застосовують?


19
@John: +1 Я згоден, що це найцікавіше явище. Я впевнений, що Unkwntech - не єдиний знаючий та здатний чоловік мати прогалини в тому, що інші вважають фундаментальною лексикою. Просто програма показує дуже широкий предмет.
AnthonyWJones

9
Він може ним скористатися, лише не давши йому ім'я.
Ейден Белл

10
@Aamir: Я не впевнений, що розумно вважати, що хтось із 8k знатиме всі фундаментальні матеріали у всіх областях програмування. Також я не вважаю, що це означає, що система репутації є недосконалою. Хтось може завоювати значну репутацію, задавши багато хороших питань. Я думаю, що наша природна реакція на це одкровення просто демонструє, що ми (програмісти) мають природну тенденцію бути трохи вузько налаштованими (не погано, коли нам потрібно бути дуже хорошими в якійсь конкретній технічній області), і це має свої недоліки.
AnthonyWJones

43
Ви, здається, у вас дуже обмежений погляд на програмування. Я знаю хлопців, які займаються вбудованою розробкою, які взагалі не знають (або потребують) концепцій ОО. Їх коротка інформація полягає в тому, щоб вивести з коду кожен останній атом продуктивності, і це все - код, над яким вони працюють, ніколи не ввійде у світ об’єктів, і вони, на щастя, досить близькі до виходу на пенсію, про що їм не потрібно турбуватися. вивчення нових фантастичних понять, таких як об'єкти, поліморфізм та назви змінних з більш ніж двома літерами :-)
paxdiablo

29
Як же ви дізнаєтеся що - то? Ніхто не прийшов у цей світ, знаючи PHP OOP та схеми дизайну, тому всі ви в якийсь момент повинні були навчитися цьому, в коледжі, відповіді тут і т. Д. Не говоріть про когось ", не наважившись не знати складних процедур кодування ", і замість цього вважають, що вони хочуть дізнатися це, що є хорошою справою і сенсом цього сайту. Використовуйте свій час, допомагаючи їм, як я впевнений, що вам допомагали в минулому. Якби протягом історії людини, замість обміну знаннями, відповідь була: "Що? Га! Ти цього не знаєш? ..", ми все ще були б у темні віки ..
Джеймс

Відповіді:


544

Якщо подумати про грецькі корені цього терміна, це повинно стати очевидним.

  • Poly = багато: багатокутник = багатогранний, полістирол = багато стиренів (а) , поліглот = багато мов тощо.
  • Морф = зміна або форма: морфологія = вивчення біологічної форми, Морфей = грецький бог снів, здатний приймати будь-яку форму.

Отже, поліморфізм - це здатність (в програмуванні) представляти один і той же інтерфейс для різних базових форм (типів даних).

Наприклад, у багатьох мовах цілі числа та поплавці неявно поліморфні, оскільки ви можете додавати, віднімати, множувати тощо, незалежно від того, що типи різні. Вони рідко розглядаються як об'єкти у звичайному терміні.

Але, в тому ж чином, як клас BigDecimalабо RationalабоImaginary також може забезпечити ці операції, навіть якщо вони працюють на різних типах даних.

Класичним прикладом є Shape клас та всі класи, які можуть успадковувати його (квадрат, коло, додекаедр, неправильний багатокутник, бризок тощо).

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

Зробивши клас відповідальним за його код, а також його дані, ви можете досягти поліморфізму. У цьому прикладі кожен клас мав би свою Draw()функцію, і клієнтський код міг би просто виконувати:

shape.Draw()

щоб отримати правильну поведінку для будь-якої форми.

Це на відміну від старого способу виконання речей, у яких код був відокремлений від даних, і ви мали б такі функції, як drawSquare()і drawCircle().

Об'єктна орієнтація, поліморфізм та успадкування - це тісно пов'язані між собою поняття, і їх важливо знати. Протягом моєї тривалої кар'єри було багато "срібних куль", які в основному просто виганяли, але парадигма ОО виявилася гарною. Вивчіть це, зрозумійте, полюбите - будете раді, що зробили :-)


(а) Я спочатку писав це як жарт, але виявилося правильним і, отже, не таким смішним. Мономерний стирол, як правило, виготовляється з вуглецю і водню , а полістирол виготовляється з таких груп,C8H8(C8H8)n .

Можливо, я мав би сказати, що поліп був багатьма явищами листа, pхоча, тепер, коли мені довелося пояснити жарт, навіть це не здається смішним.

Іноді вам слід просто кинути, поки ви позаду :-)


50
Грецька, а не латинська :) ("y" і "ph" - це подарунки). А грецькою мовою - морф - це просто «форма», або «форма» - англійське значення « змінити форму» на «морф» - пізніший розвиток
AakashM,

16
Поліморфізм не пов'язаний з ООП, але ООП пов'язаний з поліморфізмом, оскільки він по суті підтримує його (якщо вважати його гідною мовою ООП). Подивіться на ФП інші приклади поліморфізму.
альтернатива

9
Ці два рядки зробили для мене хитрість:Poly = many and Morph = change or form
Джо Смо

3
Поліп короткий для polypo (u) s. І pous нога грецькою мовою. ;-)
Дірк

2
@Shaun, я думаю, ви, можливо, використовуєте термін "інтерфейс" у занадто буквальному / обмежувальному сенсі - я мав на увазі це як англійський термін, а не визначення, характерне для якоїсь довільної комп'ютерної мови. Це не означає точно таку ж функцію з абсолютно однаковими параметрами, це просто спосіб впливати на «об’єкти» таким же чином, незалежно від їх конкретного типу. Сюди можна віднести перевантаження методу різними типами параметрів, а також більш чисту форму поліморфізму.
paxdiablo

250

Поліморфізм - це коли ви можете ставитися до об'єкта як до загальної версії чогось, але коли ви отримуєте доступ до нього, код визначає, який саме тип він є, і називає асоційований код.

Ось приклад у 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));
    }
}

У цьому прикладі ми створюємо список автомобіля базового класу, який не знає про те, скільки коліс має кожен з його підкласів, але знає, що кожен підклас відповідає за те, щоб знати, скільки у нього коліс.

Потім ми додаємо до списку велосипед, автомобіль та вантажівку.

Далі ми можемо переглядати кожен транспортний засіб у списку та обробляти їх усі однаково, проте коли ми отримуємо доступ до властивостей кожного колеса транспортного засобу, клас транспортного засобу делегує виконання цього коду відповідному підкласу.

Цей код, як кажуть, є поліморфним, оскільки точний код, який виконується, визначається підкласом, на який посилається під час виконання.

Я сподіваюся, що це вам допоможе.


6
Я думаю, що це дуже хороший приклад для чіткого відображення батьківського інтерфейсу, і це не до того часу, поки об'єкт не буде встановлено, що потрібна конкретна версія, тобто автомобіль проти автомобіля
провідний00

1
Я б сказав, що це найяскравіший приклад, хоча якщо ви програміст PHP, це посилання може бути простіше переглянути ПЕРШИЙ, а потім все-таки подивитись на це після: code.tutsplus.com/tutorials/…
Олівер Вільямс

Також (виходячи за рамки ОП) зазначити, що ми обмежуємо аналіз відомими об'єктами; ми не передаємо об’єкт (наприклад, файл імпорту), а потім визначаємо, який тип він (Excel, CSV, YAML, SQL і т.д. тощо). Для цього потрібен був би якийсь заводський клас для Class_Excel, Class_CSVщоб його називали або мав Readerклас. У будь-якому випадку, якийсь ітераційний, якщо / тоді / інше доведеться десь зберігати.
Олівер Вільямс

@Antony Gibbs: це справді хороший приклад (перелік загальних типів), який має сенс для мене .... інакше, що велика справа у тому, щоб кожен клас мав свою функцію колеса, не успадковуючи базовий клас? Чи є ще переліки, крім списку, які були б корисні для поліморфних?
TTT

195

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

Поліморфізм - це довге слово для дуже простого поняття.

Поліморфізм описує схему об'єктно-орієнтованого програмування, в якому класи мають різні функціональні можливості при спільному використанні загального інтерфейсу.

Краса поліморфізму полягає в тому, що код, що працює з різними класами, не повинен знати, який клас він використовує, оскільки всі вони використовуються однаково. Справжня світова аналогія поліморфізму - це кнопка. Всі знають, як користуватися кнопкою: ви просто натискаєте на неї. Що кнопка "робить", однак, залежить від того, для чого вона пов'язана, і контексту, в якому вона використовується, але результат не впливає на те, як вона використовується. Якщо ваш начальник скаже вам натиснути кнопку, у вас вже є вся інформація, необхідна для виконання завдання.

У світі програмування поліморфізм використовується для того, щоб зробити додатки більш модульними та розширеними. Замість брудних умовних висловлювань, що описують різні напрямки дій, ви створюєте взаємозамінні об'єкти, які ви вибираєте, виходячи з ваших потреб. Це основна мета поліморфізму.


10
Чи не аналогія кнопок більше стосується поняття абстракції?
thewpfguy

6
Оригінальне джерело: code.tutsplus.com/tutorials/…
Хтось

8
@Mantriur: Це дійсно плагіат, і ми маємо правила проти цього: stackoverflow.com/help/referencing Але враховуючи його оцінку зараз і те, що старі публікації звільнені від втрати повтору при видаленні відповіді, я не впевнений, чи видалити його тепер відверто щось би покращило. Наступною найкращою альтернативою буде просто редагування атрибуції від імені користувача, хоча я переконаний, що користувачі несуть відповідальність за цитування джерел у власних відповідях.
BoltClock

1
Я вважаю, що неправильно розуміти, що поліморфізм характерний для класів та / або об'єктно-орієнтованого програмування, бачачи, як спеціальний поліморфізм або параметричний поліморфізм не обов'язково вимагають класів та / або об'єктів. Я думаю, що ця відповідь говорить про підтипу (також відомий як політип поліморфізму або включення поліморфізм).
StubbornShowaGuy

64

Якщо хтось скаже CUT цим людям

  1. Хірург
  2. Перукар
  3. Актор

Що станеться?

  • Хірург почав робити надрізи.
  • Перукар почав стригти чиєсь волосся.
  • Актор різко перестане виступати з поточної сцени, чекаючи режисерських вказівок.

Отже, вище представлення показує, що таке поліморфізм (однойменна назва, різна поведінка) в ООП.

Якщо ви збираєтесь на співбесіду, а інтерв'юер просить вас розповісти / показати живий приклад поліморфізму в тій же кімнаті, в якій ми сидимо, скажімо,

Відповідь - двері / вікна

Цікаво, як?

Через двері / вікно - людина може прийти, повітря може прийти, світло може прийти, може дощ і т.д.

Щоб зрозуміти це краще і просто, я використав вище приклад .. Якщо вам потрібна посилання на код, дотримуйтесь наведених вище відповідей.


5
Я не думаю, що це чудовий приклад, тому що це може змусити недосвідчених людей думати, що якщо у двох класах є .foo()метод, то вони повинні мати спільний інтерфейс. Однак це неправда і призводить до неправильних абстракцій. Інтерфейс повинен визначати роль, яку потрібно відігравати, яка може мати багато різних реалізацій, але всі витягуються з одного і того ж набору вхідних даних і повертають щось із того ж набору результатів. Вхід до x.cut(...)хірурга, стиліста чи актора не є однаковим, і не є результатом.
Метт Кляйн

37

Просте пояснення за аналогією

У президента США використовується поліморфізм. Як? Ну, у нього є багато радників:

  1. Військові радники
  2. Юридичні консультанти
  3. Ядерні фізики (як радники)
  4. Медичні консультанти
  5. тощо.

Кожен повинен відповідати лише за одне: Приклад:

Президент не є знавцем покриття цинком чи квантовою фізикою. Він не знає багатьох речей, але він знає лише одне: як керувати країною.

Це якось те саме з кодом: проблеми та обов'язки слід розділити на відповідні класи / люди. Інакше ти мав би, щоб президент знав буквально все на світі - всю Вікіпедію. Уявіть, що вся вікіпедія є у класі вашого коду: це було б кошмаром.

Чому для президента погана ідея знати всі ці конкретні речі?

Якби президент конкретно сказав людям, що робити, це означає, що президентові потрібно знати точно , що робити. Якщо президент сам повинен знати конкретні речі, це означає, що коли вам потрібно внести зміни, то вам потрібно буде це зробити в двох місцях, а не в одному.

Наприклад, якщо EPA змінює закони про забруднення, то коли це станеться: вам доведеться внести зміни до класу EPA, а також до класу Президента. Зміна коду в двох місцях, а не в одному, може бути небезпечним - адже це набагато важче підтримувати.

Чи є кращий підхід?

Є кращий підхід: президенту не потрібно знати специфіку будь-чого - він може вимагати найкращих порад від людей, спеціально доручених цим займатися.

Він може використовувати поліморфний підхід до управління країною.

Приклад використання поліморфного підходу:

Все, що робить президент, - це попросити людей порадити його - і це те, що він насправді робить у реальному житті - і це те, що повинен робити хороший президент. всі його радники реагують по-різному, але всі вони знають, що означає президент: Поради (). У його кабінет потрапляють сотні людей. Насправді не важливо, хто вони. Все, що знає президент, це те, що коли він просить їх "порадити", вони знають, як відповісти :

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

Такий підхід дозволяє президенту керувати країною буквально, нічого не знаючи про військові речі, про охорону здоров'я чи міжнародну дипломатію: деталі залишаються експертам. Єдине, що повинен знати президент, це: «Порадьте ()».

Чого ти не хочеш:

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

Я дуже сподіваюся, що це вам допоможе. Якщо ви нічого не розумієте, опублікуйте коментар, і я спробую ще раз.


4
Фантастичний приклад! Дякую.
Іман Седігі

1
Дуже цікава аналогія. Дякую.
ніжhtang

1
@TTT, оскільки (1) кожен раз, коли у вас є новий радник, тоді вам доведеться змінювати клас президента - ви не хочете вносити x2 зміни. тільки один. (2) по-друге, якщо вам доведеться змінити існуючого радника, то, можливо, вам доведеться повернутися назад і змінити один із цих трьох дзвінків у класі президента - ви дійсно хочете зробити одну зміну, а не дві. (3) якби у вас було три окремі дзвінки, тоді вам доведеться запитати в класі президента: if healthAdvisor? then do this:і if petraus then do that etc.цю схему потрібно буде повторити, і це є необхідним і складним. див. вище редагувати.
BKSpurgeon

1
@TTT так, ти маєш рацію. але мені доведеться повільно вводити цю концепцію читачам, інакше вони не зрозуміють. я додав подальші зміни. будь ласка, порадьте, чи потрібні роз'яснення
BKSpurgeon

1
Інтерфейс базового класу @TTT проти інтерфейсу - це рішення, яке програмісти повинні приймати, роблячи поліморпізм. дивіться тут для більш докладної інформації: stackoverflow.com/questions/56867/interface-vs-base-class
BKSpurgeon

24

Поліморфізм - це здатність ставитися до класу об'єкта так, ніби це батьківський клас.

Наприклад, припустимо, що існує клас, який називається Animal, і клас під назвою Dog, який успадковується від Animal. Поліморфізм - це здатність ставитися до будь-якого об'єкта Собаки як до тваринного предмета так:

Dog* dog = new Dog;
Animal* animal = dog;

Цікаво, як це пов’язано з (популярним) поясненням, яке дав @Ajay Patelclasses have different functionality while sharing a common interface
BornToCode

1
@BornToCode Батьківський клас є / надає той загальний інтерфейс.
grokmann

1
Поліморфізм не потребує підтипу.
Шон Люттін

22

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

Це концепція об'єктно-орієнтованого програмування. Здатність різних об'єктів реагувати, кожен по-своєму, на однакові повідомлення, називається поліморфізмом.

Поліморфізм зумовлений тим, що кожен клас живе у власному просторі імен. Імена, призначені у визначенні класу, не суперечать іменам, призначеним у будь-якому місці поза ним. Це справедливо як для змінних екземплярів у структурі даних об'єкта, так і для методів об'єкта:

  • Так само, як поля структури С знаходяться в захищеному просторі імен, так і змінні екземпляри об'єкта.

  • Назви методів також захищені. На відміну від імен функцій 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.java

public class Car {

    int price;
    String name;
    String color;

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

}

Давайте реалізуємо приклад Ford Car.

Ford розширює тип автомобіля для успадкування всіх його членів (властивості та методи).

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 також розширює тип автомобіля та реалізує метод пересування по-своєму.

Переоцінка методів є важливою особливістю для поліморфізму. Використовуючи переопределення методів, типи Sub можуть змінити спосіб роботи методів, доступних через спадкування.

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 я створив три об'єкти - автомобіль, Ford і Honda. Усі три об’єкти відносяться до типу Автомобіль.

Будь ласка, зауважте тут важливий момент, що тип суперкласу може посилатися на тип підкласного об'єкта, але побічний вірш неможливий. Причина полягає в тому, що всі члени суперкласу доступні до підкласу за допомогою успадкування, а під час компіляції компілятор намагається оцінити, чи є у базового типу, який ми використовуємо, метод, до якого він намагається отримати доступ.

Отже, для автомобіля посилань, f і h у прикладі Polymorphism, метод переміщення існує від типу Car. Отже, компілятор проходить процес компіляції без жодних питань.

Але коли мова йде про виконання часу виконання, віртуальна машина викликає методи на об'єктах, які є підтипами. Отже, метод move () викликається з їх відповідних реалізацій.

Отже, всі об'єкти мають тип Car, але під час виконання виконання залежить від Об'єкта, на якому відбувається виклик. Це називається поліморфізмом.


Концепція перевантаження не має нічого спільного із спадщиною та поліморфізмом.
srk

@srk Метод перевантаження є одним із способів реалізації поліморфізму. Його часто відносять до статичного або спеціального поліморфізму. wiki.c2.com/?CategoryPolymorphism
Shaun Luttin

12

Зазвичай це стосується здатності об'єкта типу A поводитись як об'єкт типу B. У об'єктно-орієнтованому програмуванні це зазвичай досягається успадкуванням. Деякі посилання на wikipedia, щоб прочитати більше:

EDIT: виправлені зламані ланки.


10
"здатність об'єкта типу A вести себе як об'єкт типу B" - це не точне визначення. Я б сказав, що це більше схоже на здатність поводитися з об’єктом типу A, як на об’єкт типу B.
Артем Баргер

Так. Можливо, це краще фразування.
JesperE

Для повноти багато мов реалізують поліморфізм через типи качок, наприклад, Python.
ілля н.

Цікаво, як це пов’язано з (популярним) поясненням, яке дав @Ajay Patelclasses have different functionality while sharing a common interface
BornToCode

9

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

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
}

Ви можете передати лише Кубок замість конкретного екземпляра. Це допомагає в цілому, оскільки вам не потрібно вказувати конкретний екземпляр () для кожного типу чашки


2
Це конкретно підтип поліморфізму.
Шон Люттін

@ vinko-vrsalovic: що таке розробка програмного забезпечення, як у сільській Америці?
TTT

8

Я знаю, що це давнє запитання з великою кількістю хороших відповідей, але я хотів би включити відповідь в одному реченні:

Поводження з похідним типом так, ніби це базовий тип.

Наведено багато прикладів, які показують це в дії, але я вважаю, що це хороша стисла відповідь.


2
Це підтипізація, яка є лише одним із видів поліморфізму.
Shaun Luttin

@ShaunLuttin Ви можете вказати мені на будь-які ресурси, щоб дізнатися більше про інші види поліморфізму?
Abe Miessler

Вони є "спеціальним поліморфізмом" та "параметричним поліморфізмом", доповненням до "підтипового поліморфізму".
Шон Люттін

8

(Я переглядав іншу статтю про щось зовсім інше .. і поліморфізм вискочив ... Тепер я подумав, що знаю, що таке Поліморфізм .... але, мабуть, не таким красивим способом пояснив. Хотів записати це десь.) краще все-таки поділитися ...)

http://www.eioba.com/a/1htn/how-i-explained-rest-to-my-wife

читати далі з цієї частини:

..... поліморфізм. Це примхливий спосіб сказати, що різні іменники можуть мати одне і те ж дієслово.


5

Взагалі кажучи, це можливість інтерфейсу декількох різних типів об'єктів за допомогою одного і того ж або поверхнево подібного API. Існують різні форми:

  • Перевантаження функцій: визначення декількох функцій з однаковою назвою та різних типів параметрів, таких як sqrt (float), sqrt (double) та sqrt (комплекс). У більшості мов, які це дозволяють, компілятор автоматично вибере правильний для типу аргументу, що передається йому, таким чином, це поліморфізм часу компіляції.

  • Віртуальні методи в OOP: метод класу може мати різні реалізації з урахуванням специфіки його підкласів; Кажуть, що кожне з них переосмислює реалізацію, задану в базовому класі. З огляду на об'єкт, який може бути базовим класом або будь-яким з його підкласів, правильна реалізація вибирається на льоту, таким чином, це поліморфізм під час виконання.

  • Шаблони: особливість деяких мов ОО, за допомогою яких функція, клас тощо можуть бути параметризовані за типом. Наприклад, ви можете визначити загальний клас шаблонів "список", а потім інстанціювати його як "список цілих чисел", "список рядків", можливо, навіть "список списків рядків" тощо. Як правило, ви пишете код один раз для структури даних довільного типу елементів, і компілятор генерує його версії для різних типів елементів.


4

Термін поліморфізм походить від:

полі = багато

морфізм = здатність до змін

У програмуванні поліморфізм - це "техніка", яка дозволяє "дивитися" на об'єкт як на більш ніж один тип речей. Наприклад:

Об'єкт студента - це також об’єкт людини. Якщо ви "дивитесь" (тобто ролі) на студента, ви, ймовірно, можете запитати посвідчення студента. Ви не завжди можете зробити це з людиною, правда? (людина не обов'язково є студентом, тому може не мати посвідчення студента). Однак людина, ймовірно, має ім’я. Студент теж робить.

Підсумок, "дивлячись" на один і той же об'єкт з різних "ракурсів", може давати вам різні "точки зору" (тобто різні властивості або методи)

Тож ця методика дозволяє будувати речі, на які можна "дивитися" з різних кутів.

Чому ми використовуємо поліморфізм? Для початку ... абстракція. На даний момент має бути достатньо інформації :)


3

Давайте скористаємось аналогією. Для даного музичного сценарію кожен музикант, який його грає, дає свій власний штрих в інтерпретації.

Музикант може бути абстрагований інтерфейсами, жанр, до якого належить музикант, може бути класом abstrac, який визначає деякі глобальні правила інтерпретації, і кожен музикант, який грає, може моделювати конкретний клас.

Якщо ви слухач музичного твору, у вас є посилання на сценарій, наприклад, "Фуга і токата" Баха, і кожен музикант, який його виконує, робить це поліморфно по-своєму.

Це лише приклад можливого дизайну (на Java):

public interface Musician {
  public void play(Work work);
}

public interface Work {
  public String getScript();
}

public class FugaAndToccata implements Work {
  public String getScript() {
    return Bach.getFugaAndToccataScript();
  }
}

public class AnnHalloway implements Musician {
  public void play(Work work) {
    // plays in her own style, strict, disciplined
    String script = work.getScript()
  }
}

public class VictorBorga implements Musician {
  public void play(Work work) {
    // goofing while playing with superb style
    String script = work.getScript()
  }
}

public class Listener {
  public void main(String[] args) {
    Musician musician;
    if (args!=null && args.length > 0 && args[0].equals("C")) {
      musician = new AnnHalloway();
    } else {
      musician = new TerryGilliam();
    }
    musician.play(new FugaAndToccata());
}

1
AnnHallowayі VictorBorgaвідчуваєте, що вони повинні бути предметами, а не класами - ваш приклад краще читатиметься, наприклад. public class Pianist implements Musicianі victorBorge = new Pianist();т. д.
Пшемек Д

3

Я представив огляд поліморфізму на високому рівні для іншого питання:

Поліморфізм у с ++

Сподіваюся, це допомагає. Екстракт ...

... це допомагає почати з простого тесту на нього та визначення [поліморфізму]. Розглянемо код:

Type1 x;
Type2 y;

f(x);
f(y);

Тут f()потрібно виконати деяку операцію, яка задається значеннями xі yяк вхідні дані. Щоб бути поліморфним, він f()повинен вміти працювати зі значеннями щонайменше двох різних типів (наприклад, intта double), знаходячи та виконуючи відповідний типу код.

(продовження в поліморфізмі в c ++ )


3

Поліморфізм - це здатність об'єкта, яку можна прийняти у багатьох формах. Наприклад, у людському класі людина може діяти у багатьох формах, коли ми говоримо про стосунки. ПРИКЛАД: Чоловік є батьком свого сина, а він - дружиною, і він вчитель для своїх учнів.


3

Поліморфізм - це здатність об’єкта набувати багатьох форм. Найбільш поширене використання поліморфізму в ООП відбувається, коли посилання на батьківський клас використовується для позначення об'єкта дочірнього класу. У цьому прикладі, який написаний на Java, ми маємо три типи транспортних засобів. Ми створюємо три різні об’єкти і намагаємося запустити їх колеса методом:

public class PolymorphismExample {

    public static abstract class Vehicle
    {
        public int wheels(){
            return 0;
        }
    }

    public static class Bike extends Vehicle
    {
        @Override
        public int wheels()
        {
            return 2;
        }
    }

    public static class Car extends Vehicle
    {
        @Override
        public int wheels()
        {
            return 4;
        }
    }

    public static class Truck extends Vehicle
    {
        @Override
        public int wheels()
        {
            return 18;
        }
    }

    public static void main(String[] args)
    {
        Vehicle bike = new Bike();
        Vehicle car = new Car();
        Vehicle truck = new Truck();

        System.out.println("Bike has "+bike.wheels()+" wheels");
        System.out.println("Car has "+car.wheels()+" wheels");
        System.out.println("Truck has "+truck.wheels()+" wheels");
    }

}

Результат:

Результат

Для отримання додаткової інформації відвідайте https://github.com/m-vahidalizadeh/java_advanced/blob/master/src/files/PolymorphismExample.java . Я сподіваюся, що це допомагає.


Так, але ви не пояснили, які переваги поліморфізму. Очевидно, є коротший код, де ви видалили б клас транспортного засобу, і він все одно буде працювати (звичайно, з іншим об'єктом оголошення, звичайно).
Корнелій

Я не пояснив, оскільки людина, яка поставила запитання, не питала про переваги. Він запитав: "Що таке поліморфізм, для чого він використовується, і як він використовується?". Щодо коду, якщо ви можете це зробити краще, будь ласка, опублікуйте свою відповідь. Отже, наша громада може цим користуватися. Дякуємо за ваш коментар
Мохаммед

Вибачте, не хотілося звучати грубо, інші теж не пояснили. Принаймні, ви потрудилися набрати код. У будь-якому випадку він запитав, що це таке, але жоден із прикладів на цій сторінці не пояснює, що це таке. Ви всі просто представляєте складний спосіб отримати ті ж результати, що і цей: s28.postimg.org/jq8vl6031/Poly.jpg, і ніхто не піклується пояснити, чому б хто-небудь хотів використовувати поліморфізм, які його вигоди або цілі, що не могло мати було зроблено, якщо він не використовувався? Все, що я бачу на цій сторінці, - це пропозиція піднятися до своєї квартири за допомогою сходів, а не ліфтом ..
Корнелій

.. не помічаючи, що на ньому стоїть прапор, який занадто великий, щоб підходити до ліфта. Я не знаю, як поштовий індекс, тому я не можу бути дуже корисним ...
Корнелій

2

Поліморфізм - це здатність програміста писати однойменні методи, які роблять різні речі для різних типів об'єктів, залежно від потреб цих об'єктів. Наприклад, якщо ви розробляли клас, який називається, Fractionі клас, який називається ComplexNumber, обидва можуть включати метод, який називається display(), але кожен з них реалізував би цей метод по-різному. Наприклад, у PHP, ви можете реалізувати його так:

//  Class definitions

class Fraction
{
    public $numerator;
    public $denominator;

    public function __construct($n, $d)
    {
        //  In real life, you'd do some type checking, making sure $d != 0, etc.
        $this->numerator = $n;
        $this->denominator = $d;
    }

    public function display()
    {
        echo $this->numerator . '/' . $this->denominator;
    }
}

class ComplexNumber
{
    public $real;
    public $imaginary;

    public function __construct($a, $b)
    {
        $this->real = $a;
        $this->imaginary = $b;
    }

    public function display()
    {
        echo $this->real . '+' . $this->imaginary . 'i';
    }
}


//  Main program

$fraction = new Fraction(1, 2);
$complex = new ComplexNumber(1, 2);

echo 'This is a fraction: '
$fraction->display();
echo "\n";

echo 'This is a complex number: '
$complex->display();
echo "\n";

Виходи:

This is a fraction: 1/2
This is a complex number: 1 + 2i

Деякі з інших відповідей, мабуть, означають, що поліморфізм використовується лише у поєднанні з успадкуванням; наприклад, можливо, Fractionі ComplexNumberобидва реалізують абстрактний клас, який називається, Numberякий має метод display(), який і дробові фракції та ComplexNumber зобов'язані застосувати. Але вам не потрібно спадок, щоб скористатися поліморфізмом.

Принаймні в динамічно набраних мовах, таких як PHP (я не знаю про C ++ або Java), поліморфізм дозволяє розробнику викликати метод, не обов'язково знаючи тип об'єкта заздалегідь, і довіряючи, що правильна реалізація методу буде бути викликаним. Наприклад, скажіть, що користувач вибирає тип Numberствореного:

$userNumberChoice = $_GET['userNumberChoice'];

switch ($userNumberChoice) {
    case 'fraction':
        $userNumber = new Fraction(1, 2);
        break;
    case 'complex':
        $userNumber = new ComplexNumber(1, 2);
        break;
}

echo "The user's number is: ";
$userNumber->display();
echo "\n";

У цьому випадку відповідне display() буде викликаний метод, навіть якщо розробник не може знати заздалегідь, чи вибере користувач дріб або комплексне число.


2
Це не поліморфізм. Це два класи, що мають однакові методи. Їх потрібно було б пов’язати базовим класом або інтерфейсом, який називається "відображуваним" або чимось подібним, і тоді інші методи просто дбають про те, щоб об'єкт був тип "відображуваним", а не складним чи дробовим.
Pod

Я завжди вважав, що поліморфізм - це "два класи, що мають методи одного і того ж". Насправді, цитуючи Стефана Кочана (від якого я безсоромно відриваю цей приклад Фракції / Складні), "здатність ділитися однаковим іменем методу в різних класах відома як поліморфізм". (від Programming_In_Objective-C ) Він не згадує про необхідність зв'язувати класи через базовий клас. Можливо, в різних мовах це по-різному, я, чесно кажучи, не знаю.
Алекс Бассон

Навіть жорстке це визначення, яке цитується з опублікованої книги, я все-таки стверджую, що це неправильно. Тим більше, що, здається, стикаються між собою, мовне агностичне визначення поліморфізму. І хоча кінцевий результат такий самий, як і у поліморфізму, я б заперечував, що саме динамічна типізація дозволяє програмісту підштовхнути те, що правильна реалізація методу серед інших подібних методів називається.
vipirtti

2

У об'єктно-орієнтованому програмуванні під поліморфізмом розуміється здатність мови програмування по-різному обробляти об'єкти залежно від їх типу або класу даних . Більш конкретно, це можливість переглядати методи для похідних класів.


2

Поліморфізм буквально означає, множинні форми. (або багато форм): об’єкт з різних класів та метод однойменних назв, але робочі процеси різні. Простим прикладом може бути:

Розглянемо людину X.

Він лише одна людина, але він діє як багато. Ви можете запитати, як:

Він - син матері. Друг своїм друзям. Брат до сестри.


2

Поліморфізм в ООП означає, що клас може мати різні типи, успадкування - це один із способів реалізації поліморфізму.

наприклад, Shape - це інтерфейс, він має підтипи Square , Circle , Diamond . тепер у вас є об'єкт Square, ви можете оновити квадрат на форму автоматично, оскільки площа є формою. Але коли ви намагаєтесь скинути "Shape to Square", ви повинні зробити чіткий кастинг типу, тому що ви не можете сказати, що Shape є Square, це може бути і Circle. тож вам потрібно вручну надати це з кодом, як Square s = (Square)shape, а якщо форма - це "Коло", ви отримаєте java.lang.ClassCastException, тому що коло - це не квадрат.


2

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

Різне виконання відповідно до екземпляра класу, а не типу змінної змінної.

Довідкова змінна тип інтерфейсу може посилатися на будь-який із примірників класу, який реалізує цей інтерфейс.


1

Поліморфізм - це можливість використовувати об’єкт у заданому класі, де всі компоненти, що складають об’єкт, успадковуються підкласами даного класу. Це означає, що як тільки цей об’єкт оголошується класом, усі підкласи під ним (і їхні підкласи тощо), поки ви не досягнете найдальшого / нижчого підкласу) успадковують об'єкт і його компоненти (макіяж).

Пам'ятайте, що кожен клас потрібно зберігати в окремих файлах.

Наступний код ілюструє поліморфізм:

Суперклас:

public class Parent {
    //Define things that all classes share
    String maidenName;
    String familyTree;

    //Give the top class a default method
    public void speak(){
         System.out.println("We are all Parents");
    }
}

Батько, підклас:

public class Father extends Parent{
    //Can use maidenName and familyTree here
    String name="Joe";
    String called="dad";

    //Give the top class a default method
    public void speak(){
        System.out.println("I am "+name+", the father.");
    }
}

Дитина, ще один підклас:

public class Child extends Father {
    //Can use maidenName, familyTree, called and name here

    //Give the top class a default method
    public void speak(){
        System.out.println("Hi "+called+". What are we going to do today?");
    }
}

Метод виконання, посилається на батьківський клас для запуску:

public class Parenting{
    public static void main(String[] args) {
        Parent parents = new Parent();
        Parent parent = new Father();
        Parent child = new Child();

        parents.speak();
        parent.speak();
        child.speak();
    }
}

Зауважте, що кожен клас потрібно декларувати в окремих * .java-файлах. Код повинен складатись. Також зауважте, що ви можете постійно використовувати maidenName та familyTree далі вниз. Це поняття поліморфізму. Тут також досліджується поняття успадкування, де один клас може бути використаний або додатково визначений підкласом.

Сподіваюся, що це допомагає та дає зрозуміти. Я опублікую результати, коли знайду комп'ютер, за допомогою якого можна перевірити код. Дякую за терпіння!


2
зауважте, що кожна дитина не є батьком, тому ця структура неправильна. Вищим класом має бути дитина (якщо ви не тільки починаєте з "Особи"), що завжди буде правдою, крім Адама. Ви можете встановити його parent_id на нуль, оскільки Творця не можна визначити жодною конструкцією людського інтелекту.
Йозеф

1

Поліморфізм дозволяє одній і тій же рутині (функції, методу) діяти на різні типи.

Оскільки багато існуючих відповідей пов'язують підтипи з поліморфізмом, тут можна реалізувати три способи (включаючи підтипи) для здійснення поліморфізму.

  • Параметричний (загальний) поліморфізм дозволяє звичайній процедурі приймати один або кілька параметрів типу, крім звичайних параметрів, і працює на цих типах.
  • Поліморфізм підтипу дозволяє рутині діяти на будь-якому підтипі його параметрів.
  • Спеціальний поліморфізм, як правило, використовує рутинне перевантаження для надання поліморфної поведінки, але може посилатися і на інші реалізації поліморфізму.

Дивись також:

http://wiki.c2.com/?CategoryPolymorphism

https://en.wikipedia.org/wiki/Polymorphism_(computer_science)


0

В об'єктно-орієнтованих мовах поліморфізм дозволяє обробляти та обробляти різні типи даних через один і той же інтерфейс. Наприклад, розглянемо спадкування в C ++: Клас B походить від класу А. Покажчик типу A * (вказівник на клас A) може використовуватися для обробки як об'єкта класу A, так і об'єкта класу B.


0

Поліморфізм в термінах кодування - це коли ваш об'єкт може існувати у вигляді декількох типів шляхом успадкування тощо. Якщо ви створюєте клас під назвою "Shape", який визначає кількість сторін, які має ваш об'єкт, то ви можете створити новий клас, який успадковує його, наприклад "Square ". Згодом, коли ви робите екземпляр "Квадрат", ви можете передати його назад і вперед від "Форма" до "Квадрат", якщо потрібно.


0

Поліморфізм дає вам змогу створювати один модуль, викликаючи інший, і все ж мати точку залежності компіляції часу від потоку управління, а не з потоком управління.

Використовуючи поліморфізм, модуль високого рівня не залежить від модуля низького рівня. Обидва залежать від абстракцій. Це допомагає нам застосувати принцип інверсії залежності ( https://en.wikipedia.org/wiki/Dependency_inversion_principle ).

Тут я знайшов вищевикладене визначення. Приблизно через 50 хвилин на відео інструктор пояснює вищезазначене. https://www.youtube.com/watch?v=TMuno5RZNeE


0

Що таке поліморфізм?

Поліморфізм - це здатність:

  • Виконайте операцію над екземпляром спеціалізованого типу, лише знаючи її узагальнений тип, називаючи метод спеціалізованого типу, а не метод узагальненого типу: це динамічний поліморфізм .

  • Визначте кілька методів, що мають ім'я збереження, але мають різні параметри: це статичний поліморфізм .

Перше, якщо історичне визначення і найважливіше.

Для чого використовується поліморфізм?

Це дозволяє створити сильно типізовану послідовність ієрархії класів і робити деякі магічні речі, такі як управління списками об'єктів різних типів, не знаючи їх типів, але лише один їх батьківський тип, а також прив'язки даних.

Сильний і слабкий набір тексту

Зразок

Ось такі фігури, як точка, лінія, прямокутник і коло, що виконують операцію Draw (), беручи або нічого, або параметр, щоб встановити тайм-аут, щоб стерти його.

public class Shape
{
 public virtual void Draw()
 {
   DoNothing();
 }
 public virtual void Draw(int timeout)
 {
   DoNothing();
 }
}

public class Point : Shape
{
 int X, Y;
 public override void Draw()
 {
   DrawThePoint();
 }
}

public class Line : Point
{
 int Xend, Yend;
 public override Draw()
 {
   DrawTheLine();
 }
}

public class Rectangle : Line
{
 public override Draw()
 {
   DrawTheRectangle();
 }
}

var shapes = new List<Shape> { new Point(0,0), new Line(0,0,10,10), new rectangle(50,50,100,100) };

foreach ( var shape in shapes )
  shape.Draw();

Тут клас Shape і Shape.Draw () повинні бути позначені як абстрактні.

Вони не для того, щоб зрозуміти.

Пояснення

Без поліморфізму, використовуючи абстрактно-віртуальне переосмислення, розбираючи фігури, лише метод Spahe.Draw () називається CLR, не знаю, яким методом викликати. Отже, він називає метод типу, на який ми діємо, і тут тип - "Форма" через оголошення списку. Тож код взагалі нічого не робить.

За допомогою поліморфізму CLR здатний зробити висновок про реальний тип об'єкта, на який ми діємо, використовуючи те, що називається віртуальною таблицею. Отже, це називає хороший метод, і тут виклик Shape.Draw (), якщо Shape є Point, називає Point.Draw (). Так код малює фігури.

Більше читання

C # - Поліморфізм (рівень 1)

Поліморфізм на Java (рівень 2)

Поліморфізм (Посібник з програмування C #)

Таблиця віртуальних методів

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.