Az objektumorientált programozásban a Liskov helyettesítési elv (LSP) az altípus fogalmának sajátos meghatározása . Barbara Liskov és Jeannette Wing fogalmazták meg a Családi értékek: Az altípus viselkedési fogalma című cikkben :
Liskov és Wing a következő sűrített készítményt javasolta:
Ha bármely típusú objektum esetében kimutatható tulajdonság , akkor minden olyan típusú objektumra igaz , amely a altípusa .A Liskov és Wing által definiált altípus fogalma a helyettesíthetőség fogalmán alapul : ha a altípusa , akkor bármely típusú objektum helyettesíthető egy típusú objektummal anélkül, hogy megváltoztatná az érintett program kívánatos tulajdonságait.
Liskov elve az aláírásokra korlátozza az altípusok meghatározását:
Számos viselkedési körülményt is meghatároznak (lásd a Szerződéses tervezés című részt ).
Liskov helyettesítési elve szorosan kapcsolódik a szerződés-programozási módszertanhoz, amely korlátozásokat eredményez, amelyek meghatározzák, hogy a szerződések miként működhetnek együtt az öröklési mechanizmusokkal :
Ezen túlmenően, Liskov helyettesítési elve azt sugallja, hogy egy új típusú kivételeket nem lehet az alosztály módszereivel dobni, kivéve, ha ezek a kivételek maguk is a szuperosztály metódusai által dobott kivételek altípusai.
Az osztályhierarchia ismeretét használó függvény megsérti az elvet, mert hivatkozást használ az alaposztályra, de ismernie kell az alosztályokat is. Egy ilyen függvény sérti a nyitott / zárt elvet, mert az alaposztályból származtatott osztály létrehozásakor módosítani kell.
Az LSP megsértésének klasszikus példája:
Számíthat arra, hogy bármilyen típusú példányt képes használni Carrébárhol, ahol egy típus Rectanglevárható.
Probléma: A négyzetnek definíció szerint négy egyenlő oldala van, ezért célszerű korlátozni a magasság és a szélesség módosítását, hogy azok mindig egyenlőek legyenek. Ha azonban egy olyan négyzetet használunk, ahol viselkedésében egy téglalapra számítanak, akkor következetlen viselkedés léphet fel: a négyzet oldalai nem változtathatók meg önállóan, ellentétben a téglalap oldalaival. Rossz megoldás az lenne, ha a tér beállítóját módosítanánk, hogy megőrizzük az utóbbi változatlanságát. De ez sértené a téglalapbeállító utólagos feltételét, amely előírja, hogy a magasságot és a szélességet egymástól függetlenül lehet módosítani.
Az egyik megoldás, hogy elkerüljük ezeket a következetlenségeket, hogy távolítsa el a változékony jellege a Carréés osztályok Rectangle. Más szavakkal, csak olvasás céljából érhetők el. Az LSP-t nem sértik, azonban a "magasság" és a "szélesség" metódusokat egy négyzetre kell végrehajtani, ami szemantikailag nem értelmes.
A megoldás nem az, ha a típust egy típus Carréhelyettesítőjének tekintjük Rectangle, és két teljesen független típusként definiáljuk őket. Ez nem mond ellent annak a ténynek, hogy a négyzet téglalap. Az osztály Carréa "négyzet" fogalmának képviselője. Az osztály Rectangleegy képviselője a koncepció „téglalap”. A képviselők azonban nem azonos tulajdonságokkal rendelkeznek, mint amit képviselnek.
Az LSP megsértésének tipikus esete könnyen felismerhető, ha az adattípus-észlelő operátort használja az objektum típusának megfelelő viselkedéshez. Például typeofC vagy C ++, isinstancePython, instanceofJava.
Például a Python függvényben:
def aFunction(anObject): if isinstance(anObject, AType): # do something elif isinstance(anObject, AnotherType): # do something else else: # default actions for the other caseEnnek az utasításnak isinstanceaz osztályon kívüli modulban történő anObjecthasználata tipikusan a Liskov-féle helyettesítési elv megsértését jelenti, és helyébe a polimorfizmus nyelvhasználatát kell beváltani .