УспадкуванняПівняк Г.Г., Бусигін Б.С., Дівізінюк М.М. та ін. Тлумачний словник з інформатики. м. Дніпропетровськ, Національний гірничий університет. 2010. С. 572ДСТУ 2481-94 «Інтелектуальні інформаційні технології» В.В. Зубенко, Л.Л. Омельчук Програмування. Поглиблений курс. – К.:Видавничо-поліграфічний центр “Київський університет”, 2011. - C.250(, помилковий переклад як „наслідування“ — це калька з рос. наследование, в українській мові "наслідування" переважно означає повторення чиєїсь поведінкиСловник української мови. Slovnyk.ua) — один з принципів об'єктно-орієнтовного програмування, який дає класу можливість використовувати програмний код іншого (базового) класу, доповнюючи його своїми власними деталями реалізації. Іншими словами, під час успадкування відбувається отримання нового (похідного) класу, який містить програмний код базового класу з зазначенням власних особливостей використання. Успадкування належить до типу is-a відношень між класами. При успадкуванні створюється спеціалізована версія вже наявного класу.
В Unified Modeling Language(UML) успадкування класів відображується на діаграмі класів.
Переваги використання успадкування Правильне використання механізму успадкування дає наступні взаємозв'язані переваги:
ефективна побудова складних ієрархій класів з можливістю їх модифікації. Роботу класів в ієрархії можна змінювати шляхом додавання нових успадкованих класів в потрібному місці ієрархії; повторне використання раніше написаного коду з подальшою його модифікацією під поставлену задачу. Своєю чергою, новостворений код також може використовуватися на ієрархіях нижчих класів; зручність в супроводі (доповнені) програмного коду шляхом введення нових класів з новими можливостями; зменшення кількості логічних помилок при розробці складних програмних систем. Повторно використовуваний код частіше тестується, а, отже, менша ймовірність наявності в ньому помилок; легкість в узгодженні різних частин програмного коду шляхом використання інтерфейсів. Якщо два класи успадковані від загального нащадка, поведінка цих класів буде однакова у всіх випадках. Це твердження виходить з вимоги, що схожі об'єкти повинні мати схожу поведінку. Саме використання інтерфейсів зумовлює схожість поведінки об'єктів; створення бібліотек коду, які можна використовувати й доповнювати власними розробками; можливість реалізовувати відомі шаблони проєктування для побудови гнучкого коду, який не змінює попередніх розробок; використання переваг поліморфізму неможливо без успадкування. Завдяки поліморфізму забезпечується принцип: один інтерфейс — декілька реалізацій; забезпечення дослідницького програмування (швидкого макетування). Таке програмування використовується у випадках, коли цілі та потреби до програмної системи на початку нечіткі. Спочатку створюється макет структури, потім цей макет поетапно вдосконалюється шляхом успадкування попереднього. Процес триває до отримання потрібного результату; ліпше розуміння структури програмної системи програмістом завдяки природному представленню механізму успадкування. Якщо при побудові складних ієрархій намагатись використовувати інші принципи, то це може значно ускладнити розуміння усієї задачі та призведе до збільшення кількості помилок.
Недоліки використання успадкування При використанні успадкування в програмах помічено такі недоліки:
неможливо змінити успадковану реалізацію під час виконання; низька швидкість виконання. Швидкість виконання програмного коду загального призначення нижча, ніж у випадку використання спеціалізованого коду, який написаний конкретно для цієї задачі. Однак, цей недолік можна виправити завдяки оптимізації коду; великий розмір програм через використання бібліотек загального призначення. Якщо для деякої задачі розробляти вузькоспеціалізований програмний код, то цей код буде займати менше пам'яти ніж код загального призначення; збільшення складності програми у випадку неправильного або невмілого використання успадкування. Програміст зобов'язаний вміти коректно використовувати успадкування при побудові ієрархій класів. В іншому випадку це призведе до великого ускладненню програмного коду, і, як результат, збільшенню кількості помилок; складність засвоєння початковими програмістами основ побудови програм, які використовують успадкування. Однак, цей недолік умовний, бо залежить від досвіду програміста.
Термінологія В об'єктно-орієнтованому програмуванні, починаючи з Simula 67, абстрактні типи данних називаются класами.
Базовий клас () — це клас, який перебуває на вершині ієрархії успадкування класів і в основі дерева підкласів, тобто не є підкласом і не має успадкувань від інших суперкласів або інтерфейсів. Базовим класом може бути абстрактний клас і інтерфейс. Будь-який не базовий клас є підкласом.
Суперклас (), батьківський клас (), предок або надклас — клас, від якого виконується успадкування в підкласах, тобто клас, від якого спадкують інші класи. Суперкласом може бути підклас, базовий клас, абстрактний клас і інтерфейс.
Підклас (), похідний клас (), дочірній клас (), клас-нащадок або клас-реалізатор — клас, який спадкує від суперкласу або інтерфейсу, тобто клас визначений через успадкування від іншого класу або деяких таких класів. Підкласом може бути суперклас.
Інтерфейс () — це структура, що визначає чистий інтерфейс класу, що складається з абстрактних методів. Інтерфейси беруть участь в ієрархії успадкування класів і інтерфейсів.
Базовий інтерфейс () — це аналог базового класу в ієрархії успадкування інтерфейсів, тобто це інтерфейс, який перебуває на вершині ієрархії успадкування.
Суперінтерфейс () або інтерфейс-предок — це аналог суперкласу в ієрархії успадкування, тобто від цього інтерфейсу виконується успадкування в підкласах і підінтерфейсах.
Інтерфейс-нащадок або похідний інтерфейс () — це аналог підкласу в ієрархії успадкування інтерфейсів, тобто це інтерфейс, який спадкує від одного або декількох суперінтерфейсів.
Ієрархія успадкування або ієрархія класів — дерево, елементами якого є класи та інтерфейси.
Застосування Успадкування є механізмом повторного використання коду () і сприяє незалежному розширенню програмного забезпечення через відкриті класи () та інтерфейси (). Встановлення відношення успадкування між класами породжує .
Типи успадкування
«Просте» успадкування «Просте» успадкування, або одинарне успадкування, описує спорідненість між двома класами: один з яких спадкує від іншого. З одного класу може виводитися багато класів, але навіть в цьому випадку подібний вид взаємозвязку залишається «простим» успадкуванням.
Абстрактні класи і створення об'єктів Для деяких мов програмування справедлива наступна концепція.
Існують «абстрактні» класи (оголошуються такими довільно або через приписані до них абстрактні методи); їх можна описувати наявними поля та методи. Створення ж об'єктів (екземплярів) означає конкретизацію, застосовну тільки до неабстрактних класів (в тому числі, до неабстрактних нащадків абстрактних), — представниками яких, в результаті, будуть створені об'єкти.
Множинне успадкування
При множинному успадкуванні клас може мати більш, ніж одного предка. В цьому випадку клас успадковує методи всіх предків. Переваги такого підходу в більшій гнучкості.
Множинне успадкування реалізовано в C++. З інших мов, що надають цю можливість, можна відмітити Python і Eiffel. Множинне успадкування підтримується в мові UML.
Множинне успадкування — потенційне джерело помилок, які можуть виникати через наявність однакових імен методів у предків. В мовах, які позиціонуются як спадкоємці C++ (Java, C# та інші), було прийнято рішення відмовитись від множинного успадкування на користь інтерфейсів. Практично завжди можна обійтися без використання даного механізму. Однак, якщо така необхідність усе ж виникла, то для розв'язання конфліктів використання успадкованих методів з однаковими іменами можливо, наприклад, застосувати операцію розширення видимості — «::» — для виклику конкретного метода конкретного предка.
Спроба вирішення проблеми наявності однакових імен методів в предках була здійснена у мові Eiffel, в якій при описі нового класу необхідно явно вказати імпортовані члени кожного з успадкованих класів і їхні імена у дочірньому класі.
Більшість сучасних об'єктно-орієнтованих мов програмуння (C#, Java, Delphi та інші) підтримують можливість одночасно успадковувати від класа-предка і реалізовувати методи декількох інтерфейсів одним і тим самим класом. Цей механізм дозволяє багато в чому замінити множинне успадкування — методи інтерфейсів необхідно перевизначати явно, що виключає помилки при успадкуванні функціональності однакових методів різних класів-предків.
Єдиний базовий клас В ряді мов програмування, усі класи, — явно або неявно, — успадковуються від деякого базового класу. Smalltalk був одним з перших мов, в яких використовувалась ця концепція. До таких мов також відносяться: Objective-C (NSObject), Perl (UNIVERSAL), Eiffel (ANY), Java (java.lang.Object), C# (System.Object), Delphi (TObject), Scala (Any).
Успадкування в мовах програмування
C++ Успадкування в C++:class A {}; // Базовий клас
class B : public A {}; // Public-успадкування class C : protected A {}; // Protected-успадкування class Z : private A {}; // Private-успадкуванняВ C++ існує три типи успадкування: public, protected, private. Специфікатори доступу членів базового класу змінюються в потомках наступним чином: Якщо клас оголошено як базовий для іншого класу зі специфікатором доступу:
public: public-члени базового класу — доступні як public-члени похідного класу; protected-члени базового класу — доступні як protected-члени похідного класу; protected: public- і protected-члени базового класу — доступні як protected-члени похідного класу; private: public- і protected-члени базового класу — доступні як private-члени похідного класу.
Одним з основних переваг public-успадкування є те, що вказівник на класи-нащадки може бути неявно перетворений у вказівник на базовий клас, тобто для прикладу вище можна написати:A* a = new B();Ця цікава можливість відкриває можливість динамічної ідентифікації типу (RTTI).
Delphi (Object Pascal) Для використання механізму успадкування в Delphi необхідно в оголошені класу в дужках class вказати клас предок: Предок:TAncestor = class private protected public //Віртуальна процедура procedure VirtualProcedure; virtual; abstract; procedure StaticProcedure; end;Нащадок:TDescendant = class(TAncestor) private protected public //Перекриття віртуальної процедуры procedure VirtualProcedure; override; procedure StaticProcedure; end;Абсолютно всі класи в Delphi є нащадками класа TObject. Якщо клас-предок не вказан, то мається на увазі, що новий клас є прямим нащадком класа TObject.
Множинне успадкування в Delphi з самого початку не підтримується, однак для тих, кому без цього не обійтись, усе ж є такі можливості, наприклад, за рахунок використання класів-помічників(англ. Class Helpers).
Python Python підтримує як одиночне, так і множинне успадкування. При доступі до атрибуту, перегляд похідних класів прохидить в порядку розширення метода (англ. method resolution order, MRO).class Ancestor1(object): # Предок-1 def m1(self): pass class Ancestor2(object): # Предок-2 def m1(self): pass class Descendant(Ancestor1, Ancestor2): # Нащадок def m2(self): pass
d = Descendant() # Ініціалізація print d.__class__.__mro__ # Порядок розширення метода:(<class '__main__.Descendant'>, <class '__main__.Ancestor1'>, <class '__main__.Ancestor2'>, <type 'object'>)З версії Python 2.2 в мові існують «класичні» класи і «нові» класи. Останні є нащадками object. «Класичні» класи будуть підтримувати включно до версії 2.6, але видалені з мови в Python 3.0.
Множинне успадкування застосовують у Python для введення в основний клас класів-домішок (англ. mix-in).
PHP Для використання механізма успадкування в PHP необхідно в оголошенні класу після імені оголошеного класу-нащадка вказати слово extends і ім'я класу-предка:class Descendant extends Ancestor {