Nie zawsze lubię Liskov, ponieważ wydaje się ograniczać to, co można zrobić z dziedziczeniem w oparciu o zachowanie, a nie "esencję". Moim zdaniem dziedziczenie zawsze miało być relacją "jest", a nie "działa dokładnie tak jak".
Mimo, że the wikipedia article idzie w szczegóły co do dlaczego jest to uważane za złe przez niektóre, używając dokładnie przykład:
Typowym przykładem, który jest niezgodny LSP jest kwadratem klasa, która wywodzi się z prostokąta class, przy założeniu, że istnieją metody getter i setter zarówno dla szerokości, jak i wysokości.
Klasa kwadratowa zawsze zakłada, że szerokość jest równa wysokości. Jeśli obiekt kwadratowy jest używany w kontekście, w którym spodziewany jest prostokąt, może wystąpić nieoczekiwane zachowanie, ponieważ wymiary kwadratu nie mogą (lub raczej nie powinny) być modyfikowane niezależnie.
Ten problem nie może być łatwo naprawiony: jeśli możemy zmodyfikować metody setera w klasie Square, aby zachować niezmienny kwadrat (tj. Zachować wymiary równe), wówczas te metody osłabią (naruszą) warunki dla Ustawniki prostokąta, które określają, że wymiary można modyfikować niezależnie.
Więc patrząc na kodzie obok równoważny kod Rectangle
:
s = Square.new(100) r = Rectangle.new(100,100)
s.width = 50 r.width = 50
puts s.height puts r.height
wyjście byłoby 50 po lewej stronie i 100 po prawej stronie.
Ale ten jest ważne nieco z artykułu, moim zdaniem:
Naruszenia LSP, jak ten, może lub nie być problemem w praktyce, w zależności od warunki końcowe lub niezmienniki, których rzeczywiście oczekuje kod, który używa klas naruszających LSP.
Innymi słowy, pod warunkiem kod korzystając klas rozumie zachowanie, nie ma problemu.
Konkluzja, kwadrat jest właściwym podzbiorem prostokąta, o luźno na tyle definicji prostokąta :-)
Lumpy Space Princess? http://www.youtube.com/watch?v=pJTrD3R5cj0 – paxdiablo
Wow, to interesujące, ale nie mogę tego zrozumieć. – mko
Yozloy, przepraszam, właśnie chciałem wyjaśnić, co masz na myśli LSP, aby ci, którzy nie są tego świadomi, nie musieli szukać. – paxdiablo