Принцип заміщення Лісков (англ. Liskov Substitution Principle, LSP) в об'єктно-орієнтованому програмуванні — це спеціальне визначення , запропоноване Барбарою Лісков у 1987 році на конференції у доповіді під назвою "Абстракція даних та ієрархія".
У своїй статті Лісков сформулювала свій принцип так:
- Нехай є властивістю правильною для об'єктів деякого типу . Тоді також має бути правильним для об'єктів типу , де — підтип типу .
Таким чином ідея Лісков про «підтип» визначає поняття заміщення — якщо S підтип T, тоді об'єкти типу T в програмі можуть бути заміщені об'єктами типу S без будь-яких змін бажаних властивостей цієї програми (наприклад, [en]).
Цей принцип — найважливіший критерій для оцінки якості ухвалених рішень при побудові ієрархій успадкування. Сформулювати його можна у вигляді простого правила: тип S буде підтипом Т тоді і тільки тоді, коли кожному об'єктові o1 типу S відповідає певний об'єкт o2 типу T таким чином, що для всіх програм P, реалізованих в термінах T, поведінка P не зміниться, якщо o2 замінити на o1.
Принцип Лісков є суворішим за поняття підтипу в теорії типів, яка вимагає тільки:
- коваріантність методів за типом результату;
- контраваріантність методів за типами аргументів;
- заборону в методах підтипу викиду винятків, які не є похідними від типів винятків, що викидаються методами базового типу.
Проєктування за контрактом
Принцип заміщення Лісков близько стосується методології проєктування за контрактом, і веде до деяких обмежень на те, як контракти можуть взаємодіяти з успадкуванням:
- Передумови не можуть бути посилені в підтипі.
- Післяумови не можуть бути послаблені в підтипі.
- Інваріанти базового типу повинні виконуватись у підтипі.
- «Історичне обмеження»: заборона модифікації стану об'єкта методами підтипу, які відсутні в базовому типі.
Функція, що обробляє ієрархію класів з порушеннями принципу Лісков, використовує посилання на базовий клас, але також вимушена мати інформацію про підклас. Така функція також порушує (принцип відкритості/закритості) оскільки її необхідно змінювати в разі появи нових похідних класів.
У цьому контексті принцип заміщення Лісков можна переформулювати так:
- Функції, які використовують посилання на базові класи, повинні мати можливість використовувати об'єкти похідних класів, не знаючи про це.
Андрей Александреску та Герб Саттер в книзі «C++ Coding Standards» описують виконання цього принципу так:
- «Підклас не повинен вимагати від коду, що його викликає, більше ніж вимагав базовий клас. І повинен надавати цьому коду не менше ніж надавав базовий клас».
На думку авторів, публічне успадкування можна використовувати тільки коли виконується принцип LSP. Приватне успадкування дозволене тільки для доступу до protected частини та заміщення віртуальних методів. Для всіх інших випадків, успадковування використовувати не бажано.
Приклад
Роберт Мартін зазначає, що до перших ознак порушення принципу підстановки Лісков є наявність функцій, які перевіряють тип отриманого аргументу для визначення своєї поведінки:
void DrawShape(const Shape& s) { if (typeid(s) == typeid(Square)) DrawSquare(static_cast<Square&>(s)); else if (typeid(s) == typeid(Circle)) DrawCircle(static_cast<Circle&>(s)); }
Таке може трапитись коли успадковані класи порушують контракт базового класу. Наприклад, квадрат можна представити як підклас прямокутника, оскільки квадрат це і є прямокутник з рівними сторонами (інший наведений ним приклад коло — вироджений випадок еліпсу).
Однак, оскільки квадрат успадкує від прямокутника обидва атрибута — ширину і висоту, то постане проблема: як гарантувати їхню рівність в методах присвоєння (так званих «сеттерах»)? Просте рішення може мати такий вигляд:
void Square::SetWidth(double w) { Rectangle::SetWidth(w); Rectangle::SetHeight(w); } void Square::SetHeight(double h) { Rectangle::SetHeight(h); Rectangle::SetWidth(h); }
Але такий код порушує принцип підстановки Лісков для тих функцій, які покладаються на збереження переданих значень:
void g(Rectangle& r) { r.SetWidth(5); r.SetHeight(4); assert(r.GetWidth() * r.GetHeight()) == 20); }
Таким чином, порушення принципу підстановки Лісков може спричиняти порушення принципу (відкритості/закритості).
Примітки
- Liskov, Barbara (4 жовтня 1987). . Архів оригіналу за 30 червня 2019. Процитовано 23 березня 2008.
- Liskov, Barbara; Jeannette Wing (July 1999). Behavioral Subtyping Using Invariants and Constraints (PS). Архів оригіналу за 30 серпня 2012. Процитовано 5 жовтня 2006.
- Robert Martin,
- Martin, Robert C. (2000). (PDF). Архів оригіналу (PDF) за 6 вересня 2015.
Thus, violations of LSP are latent violations of OCP.
Посилання
Вікіпедія, Українська, Україна, книга, книги, бібліотека, стаття, читати, завантажити, безкоштовно, безкоштовно завантажити, mp3, відео, mp4, 3gp, jpg, jpeg, gif, png, малюнок, музика, пісня, фільм, книга, гра, ігри, мобільний, телефон, android, ios, apple, мобільний телефон, samsung, iphone, xiomi, xiaomi, redmi, honor, oppo, nokia, sonya, mi, ПК, web, Інтернет
Div takozh Liskov Princip zamishennya Liskov angl Liskov Substitution Principle LSP v ob yektno oriyentovanomu programuvanni ce specialne viznachennya zaproponovane Barbaroyu Liskov u 1987 roci na konferenciyi u dopovidi pid nazvoyu Abstrakciya danih ta iyerarhiya U svoyij statti Liskov sformulyuvala svij princip tak Nehaj q x displaystyle q x ye vlastivistyu pravilnoyu dlya ob yektiv x displaystyle x deyakogo tipu T displaystyle T Todi q y displaystyle q y takozh maye buti pravilnim dlya ob yektiv y displaystyle y tipu S displaystyle S de S displaystyle S pidtip tipu T displaystyle T Takim chinom ideya Liskov pro pidtip viznachaye ponyattya zamishennya yaksho S pidtip T todi ob yekti tipu T v programi mozhut buti zamisheni ob yektami tipu S bez bud yakih zmin bazhanih vlastivostej ciyeyi programi napriklad en Cej princip najvazhlivishij kriterij dlya ocinki yakosti uhvalenih rishen pri pobudovi iyerarhij uspadkuvannya Sformulyuvati jogo mozhna u viglyadi prostogo pravila tip S bude pidtipom T todi i tilki todi koli kozhnomu ob yektovi o1 tipu S vidpovidaye pevnij ob yekt o2 tipu T takim chinom sho dlya vsih program P realizovanih v terminah T povedinka P ne zminitsya yaksho o2 zaminiti na o1 Princip Liskov ye suvorishim za ponyattya pidtipu v teoriyi tipiv yaka vimagaye tilki kovariantnist metodiv za tipom rezultatu kontravariantnist metodiv za tipami argumentiv zaboronu v metodah pidtipu vikidu vinyatkiv yaki ne ye pohidnimi vid tipiv vinyatkiv sho vikidayutsya metodami bazovogo tipu Div kovariantnist i kontravariantnist i tipi danih Proyektuvannya za kontraktomPrincip zamishennya Liskov blizko stosuyetsya metodologiyi proyektuvannya za kontraktom i vede do deyakih obmezhen na te yak kontrakti mozhut vzayemodiyati z uspadkuvannyam Peredumovi ne mozhut buti posileni v pidtipi Pislyaumovi ne mozhut buti poslableni v pidtipi Invarianti bazovogo tipu povinni vikonuvatis u pidtipi Istorichne obmezhennya zaborona modifikaciyi stanu ob yekta metodami pidtipu yaki vidsutni v bazovomu tipi Funkciya sho obroblyaye iyerarhiyu klasiv z porushennyami principu Liskov vikoristovuye posilannya na bazovij klas ale takozh vimushena mati informaciyu pro pidklas Taka funkciya takozh porushuye princip vidkritosti zakritosti oskilki yiyi neobhidno zminyuvati v razi poyavi novih pohidnih klasiv U comu konteksti princip zamishennya Liskov mozhna pereformulyuvati tak Funkciyi yaki vikoristovuyut posilannya na bazovi klasi povinni mati mozhlivist vikoristovuvati ob yekti pohidnih klasiv ne znayuchi pro ce Andrej Aleksandresku ta Gerb Satter v knizi C Coding Standards opisuyut vikonannya cogo principu tak Pidklas ne povinen vimagati vid kodu sho jogo viklikaye bilshe nizh vimagav bazovij klas I povinen nadavati comu kodu ne menshe nizh nadavav bazovij klas Na dumku avtoriv publichne uspadkuvannya mozhna vikoristovuvati tilki koli vikonuyetsya princip LSP Privatne uspadkuvannya dozvolene tilki dlya dostupu do protected chastini ta zamishennya virtualnih metodiv Dlya vsih inshih vipadkiv uspadkovuvannya vikoristovuvati ne bazhano PrikladRobert Martin zaznachaye sho do pershih oznak porushennya principu pidstanovki Liskov ye nayavnist funkcij yaki pereviryayut tip otrimanogo argumentu dlya viznachennya svoyeyi povedinki void DrawShape const Shape amp s if typeid s typeid Square DrawSquare static cast lt Square amp gt s else if typeid s typeid Circle DrawCircle static cast lt Circle amp gt s Take mozhe trapitis koli uspadkovani klasi porushuyut kontrakt bazovogo klasu Napriklad kvadrat mozhna predstaviti yak pidklas pryamokutnika oskilki kvadrat ce i ye pryamokutnik z rivnimi storonami inshij navedenij nim priklad kolo virodzhenij vipadok elipsu Odnak oskilki kvadrat uspadkuye vid pryamokutnika obidva atributa shirinu i visotu to postane problema yak garantuvati yihnyu rivnist v metodah prisvoyennya tak zvanih setterah Proste rishennya mozhe mati takij viglyad void Square SetWidth double w Rectangle SetWidth w Rectangle SetHeight w void Square SetHeight double h Rectangle SetHeight h Rectangle SetWidth h Ale takij kod porushuye princip pidstanovki Liskov dlya tih funkcij yaki pokladayutsya na zberezhennya peredanih znachen void g Rectangle amp r r SetWidth 5 r SetHeight 4 assert r GetWidth r GetHeight 20 Takim chinom porushennya principu pidstanovki Liskov mozhe sprichinyati porushennya principu vidkritosti zakritosti PrimitkiLiskov Barbara 4 zhovtnya 1987 Arhiv originalu za 30 chervnya 2019 Procitovano 23 bereznya 2008 Liskov Barbara Jeannette Wing July 1999 Behavioral Subtyping Using Invariants and Constraints PS Arhiv originalu za 30 serpnya 2012 Procitovano 5 zhovtnya 2006 Robert Martin Martin Robert C 2000 PDF Arhiv originalu PDF za 6 veresnya 2015 Thus violations of LSP are latent violations of OCP PosilannyaRobert Martin