У чому головна відмінність між спадщиною та поліморфізмом?


172

Мені було подано це питання сьогодні після закінчення модульного відкритого іспиту з книги, який я втратив. Я читав, Head first Javaі обидва визначення здавалося абсолютно однаковими. Мені було просто цікаво, яка ОСНОВНА різниця була для мого власного розуму. Я знаю, що існує ряд подібних питань до цього, але жодного я не бачив, який би дав остаточну відповідь.



Відповіді:


289

Спадкування - це коли клас походить від існуючого класу. Отже, якщо у вас є Personклас, то у вас є Studentклас, який розширюється Person, Student успадковує всі речі, які Personмає. Є деякі деталі навколо модифікаторів доступу, які ви вводите на поля / методи в Person, але це основна ідея. Наприклад, якщо у вас увімкнено приватне поле Person, воно Studentне відображатиметься, оскільки його приватні та приватні поля не видно підкласам.

Поліморфізм стосується того, як програма вирішує, які методи вона повинна використовувати, залежно від того, який тип речі він має. Якщо у вас є a Person, який має readметод, і у вас є a, Studentякий розширюється Person, який має власну реалізацію read, який метод викликається, визначається для вас часом виконання, залежно від того, чи є у вас Personабо a Student. Це стає трохи хитро, але якщо ви робите щось подібне

Person p = new Student();
p.read();

метод зчитування на Стьюденті викликається. Ось поліморфізм у дії. Ви можете виконати це завдання, тому що a Student є Person , але час виконання досить розумний, щоб знати, що фактичний тип Studentp є .

Зауважте, що деталі відрізняються між мовами. Наприклад, ви можете зробити спадщину в JavaScript, але це зовсім інше, ніж це працює в Java.


9
@ hvgtcodes, у двох словах, співвідношення надкласового підкласу - це успадкування, а концепція впровадження одного і того ж методу по-різному між батьківським класом та його підкласами, і називати їх на основі ситуації - це поліморфізм. Я прав?
Мухаммад Райхан Мухаїмін

1
@hvgotcodes , але кажуть , що якщо Person«S readметод використовує модифікатор доступу громадськості, які не будуть Studentоб'єкти бути в змозі отримати доступ до них? і тоді Student s = new Student();не буде легше? Я все ще не дуже отримую переваги від полімпорфізму.
Скорпіон83

1
@hvgotcodes Student s = new Student () буде працювати. Але скажімо, після того, як ви написали багато коду, використовуючи цю ідею, і згодом зрозумієте, що ви допустили помилку. Людина насправді не студент, це вчитель. Таким чином, ви можете просто змінити з Person p = new Student () в Person p = new учитель (), тоді це зробить ваше життя набагато простішим.
munmunbb

Моє запитання тут би через те, чому ви хочете використовувати Person p = new Student();замість цього Student p = new Student();?
PerfectContrast

@PerfectContrast Я думаю, що це корисно, коли ви хочете мати студента, водія, викладача тощо як Особу, і ви групуєте їх під Списком чи іншим. Отже, коли ви називаєте "читати" для всіх, кожен називає свій метод "читання".
savante

205

Спадкування стосується використання структури та поведінки суперкласу в підкласі.

Поліморфізм відноситься до зміни поведінки суперкласу в підкласі.


5
Чи відповідає ця відповідь, що поліморфізм вимагає успадкування?
jaco0646

6
@ jaco0646 - В контексті Java я так думаю. (В інших мовах, можливо, не так багато.) Зауважте, що "суперклас" та "підклас" тут використовуються вільно. Поліморфізм також може означати успадкування поведінки, визначеної (але не реалізованої) в інтерфейсі.
Тед Хопп

1
@AlirezaRahmani - я не розумію твій коментар. Ви маєте на увазі, що успадкування не передбачає успадкування як властивостей, так і поведінки? Це буде суперечити тому, як Java (і більшість класово-орієнтованих мов) визначають успадкування. З специфікації мови Java, § 8.4.8 : "Клас C успадковує від свого прямого суперкласу всі конкретні методи m(як staticі instance) надкласу, для якого ..." (далі деталі щодо успадкування). Для мене звучить як "повторне використання коду".
Тед Хопп

@TedHopp Спадщина - це насамперед поліморфний інструмент, але деякі люди, напевно, піддаються більшій небезпеці, намагаються використовувати його як спосіб повторного використання / спільного використання коду. Обґрунтування: «добре, якщо я успадковую, то я отримую всі методи безкоштовно», але ігноруючи той факт, що ці два класи потенційно не мають поліморфного зв’язку.
Аліреза Рахмані Халілі

1
@AlirezaRahmani - У Java (саме про це спеціально запитував ОП, відповідно до тегів), успадкування класів, безумовно, включає наслідування поведінки. Це частина визначення мови. Той факт, що це можна зловживати під час опису, є однією з слабких місць Java. (Пов'язана слабкість пов'язана з оголошенням класів для реалізації інтерфейсів просто для імпорту констант, визначених в інтерфейсі. Врешті-решт, дизайнери Java ввели import staticдля усунення цього неправильного використання інтерфейсів.) Для чистого поліморфізму в Java інструментом для використання є інтерфейси, а не успадкування класів.
Тед Хопп

63

Поліморфізм : здатність аналогічно ставитися до предметів різних типів. Приклад: Жирафа і Крокодил - це і тварини, і тварини можуть Move. Якщо у вас є примірник, Animalви можете зателефонувати, Moveне знаючи і не піклуючись про тип тварини.

Спадщина : Це один із способів досягнення одночасно поліморфізму та повторного використання коду.

Інші форми поліморфізму : Існують й інші способи досягнення поліморфізму, такі як інтерфейси, які забезпечують лише поліморфізм, але повторне використання коду (іноді код зовсім інший, наприклад, Moveдля Змії був би зовсім іншим, ніж Moveдля собаки; в такому випадку Інтерфейс був би кращим поліморфним вибором у цьому випадку.

В інших динамічних мовах поліморфізм можна досягти завдяки Duck Typing, тобто класам навіть не потрібно ділитися тим самим базовим класом або інтерфейсом, їм просто потрібен метод з тим же ім'ям. Або ще більш динамічний, як Javascript, вам навіть не потрібні заняття, просто об’єкт з тим же ім'ям методу може використовуватися поліморфно.


17

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

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


12

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

public class A {
  public void draw() { ... }
  public void spin() { ... }
}

public class B extends A {
  public void draw() { ... }
  public void bad() { ... }
}

...

A testObject = new B();

testObject.draw(); // calls B's draw, polymorphic
testObject.spin(); // calls A's spin, inherited by B
testObject.bad(); // compiler error, you are manipulating this as an A

Тоді ми бачимо , що B успадковує spinвід A. Однак, коли ми намагаємося маніпулювати об'єктом , як якщо б це був тип А, ми все ще отримуємо поведінку B для draw. drawПоведінка є поліморфним.

У деяких мовах поліморфізм та успадкування не так вже й пов’язані між собою. Наприклад, у C ++ функції, не оголошені віртуальними, успадковуються, але динамічно не розсилаються, тому ви не отримаєте цього поліморфного поведінки навіть при використанні спадкування.

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


12

Поліморфізм. Припустимо, ви працюєте в компанії, яка продає ручки. Таким чином, ви робите дуже приємний клас під назвою «Ручка», який обробляє все, що вам потрібно знати про ручку. Ви пишете всілякі класи для виставлення рахунків, доставки, створення рахунків-фактур, усі вони використовують клас Перо. Приходить шеф на день і каже: "Чудова новина! Компанія зростає, і ми зараз продаємо Книги та компакт-диски!" Не чудова новина, тому що тепер вам доведеться змінити кожен клас, який використовує перо, щоб також використовувати Book & CD. Але що робити, якщо ви спочатку створили інтерфейс під назвою "SellableProduct", і Пен реалізував цей інтерфейс. Тоді ви могли б написати всі ваші класи доставки, виставлення рахунків тощо, щоб використовувати цей інтерфейс замість ручки. Тепер все, що вам потрібно було б зробити, це створити новий клас під назвою Book & CompactDisc, який реалізує інтерфейс SellableProduct. Через поліморфізм усі інші класи могли продовжувати працювати без змін! Мати сенс?

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

Поліморхізм можливий у класі / інтерфейсі, але Спадщина завжди між 2 АБО і більше класами / інтерфейсами. Спадщина завжди відповідає "є-а" відносинам, тоді як це не завжди є поліморфізмом (який може відповідати і відносинам "є-а" / "має-а".


6

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

Напр

// This assignment is possible because B extends A
A a = new B();
// polymorphic call/ access
a.foo();

-> Хоча статичний / деклараційний тип a є A, фактичний динамічний / тип виконання є B, і таким чином a.foo () буде виконувати foo, як визначено в B, а не в A.


3

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


3

Спадкування - це поняття, пов'язане з повторним використанням коду. Наприклад, якщо у мене є батьківський клас сказати, Animalі він містить певні атрибути та методи (для цього прикладу сказати makeNoise()і sleep()), і я створюю два дочірні класи, які називаються Dogі Cat. Оскільки і собаки, і коти лягають спати однаково (я б припустив), немає необхідності додавати більше функціональності sleep()методу в Dogі Catпідкласи, надані батьківським класом Animal. Тим не менш, Dogгавкає і Catmeoew так, хочаAnimalу класі може бути метод шуму, собака та кішка видають різні шуми відносно один одного та інших тварин. Таким чином, виникає необхідність переосмислити цю поведінку для їх конкретних типів. Таким чином, визначення поліморфізму. Сподіваюся, це допомагає.


3

У документації Oracle точно вказано різницю.

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

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

поліморфізм не застосовується для полів.

Пов’язана публікація:

Поліморфізм проти перекриття проти перевантаження


1

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

Наприклад, приклад поліморфізму Java:

введіть тут опис зображення

Спадкування дозволяє похідним класам ділитися інтерфейсами та кодом їх базових класів. Це відбувається під час компіляції .

Наприклад, усі класи на платформі Java - це нащадки об'єкта (зображення ввічливості Oracle):

введіть тут опис зображення

Щоб дізнатися більше про успадкування Java та поліморфізм Java


0

Спадкування - це коли клас А успадковує всі нестатичні захищені / публічні методи / поля від усіх своїх батьків до Об'єкта.


0

Якщо ви використовуєте JAVA, це так просто:

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

Виправте мене, якщо я помиляюся.


0

Основна мета поліморфізму : Створити посилання змінної на суперклас і проведення об'єкта підкласу => об'єкт може виконувати кілька поведінок .

У спадок , підклас успадковує властивості суперкласу .


0

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


0

З успадкуванням реалізація визначається у надкласі - тому поведінка успадковується.

class Animal
{
  double location;
  void move(double newLocation)
  {
    location = newLocation;
  }
}

class Dog extends Animal;

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

interface Animal
{
  void move(double newLocation);
}

class Dog implements Animal
{
  double location;
  void move(double newLocation)
  {
    location = newLocation;
  }
}

0

Поліморфізм досягається за рахунок спадкування в Java.

├── Animal
└── (instances)
    ├── Cat
    ├── Hamster
    ├── Lion
    └── Moose

├── interface-for-diet
   ├── Carnivore
   └── Herbivore
├── interface-for-habitat
   ├── Pet
   └── Wild

public class Animal {
    void breath() {
    };
}

public interface Carnivore {
    void loveMeat();
}

public interface Herbivore {
    void loveGreens();
}

public interface Pet {
    void liveInside();
}

public interface Wild {
    void liveOutside();
}

public class Hamster extends Animal implements Herbivore, Pet {

    @Override
    public void liveInside() {
        System.out.println("I live in a cage and my neighbor is a Gerbil");
    }

    @Override
    public void loveGreens() {
        System.out.println("I eat Carrots, Grapes, Tomatoes, and More");
    }
}

public class Cat extends Animal implements Carnivore, Pet {
    @Override
    public void liveInside() {
        System.out.println("I live in a cage and my neighbr is a Gerbil");
    }

    @Override
    public void loveMeat() {
        System.out.println("I eat Tuna, Chicken, and More");
    }
}

public class Moose extends Animal implements Herbivore, Wild {

    @Override
    public void liveOutside() {
        System.out.println("I live in the forest");
    }

    @Override
    public void loveGreens() {
        System.out.println("I eat grass");
    }
}

public class Lion extends Animal implements Carnivore, Wild {

    @Override
    public void liveOutside() {
        System.out.println("I live in the forest");
    }

    @Override
    public void loveMeat() {
        System.out.println("I eat Moose");
    }
}

Hamsterклас успадковує структуру з Animal, Herbivoreі Petпроявляти поліморфний біхевіоризм з домашньої тварини.

Catклас успадковує структуру від Animal, Carnivoreа Petтакож демонструє поліморфний біхевіоризм домашнього вихованця.

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