Средства разработки приложений

         

Принцип подстановки Лисков помогает понять


Принцип подстановки Лисков помогает понять суть термина suptyping – выделение подтипа, а статья Роберта Мартина [] показывает некоторое несоответствие между наследованием в языке C++ и выделением подтипа. В этой статье принцип формулируется следующим образом: If for each object o1 of type S there is an object o2 of type T such that for all programs P defined in terms of T, the behavior of P is unchanged when o1 is substituted for o2 then S is a subtype of T. Перевод может звучать как-то так: Если для каждого объекта o1 типа S существует объект o2 типа T, такой что любая программа P, определенная в терминах T, не изменяет своего поведения при подстановке объекта o1 вместо объекта o2, то тип S является подтипом T. Эта формулировка допускает достаточно неоднозначную трактовку. Чтобы понять, что имеется в виду, рассмотрим пример из статьи с прямоугольниками и квадратами. Определим родительский класс Rectangle: ---- File:./rsl/rectangle.cpp class Rectangle{ public: virtual void SetWidth(double w){itsWidth=w;} virtual void SetHeight(double h) {itsHeight=H;} double GetHeight() const {return itsHeight;} double GetWidth() const {return itsWidth;} private: double itsWidth; double itsHeight; }; ---- End Of File:./rsl/rectangle.cpp и наследуем от него класс Square: ---- File:./rsl/square.cpp class Square : Rectangle { public: virtual void SetWidth(double w); virtual void SetHeight(double h); }; void Square::SetWidth(double w){ Rectangle::SetWidth(w); Rectangle::SetHeight(w); } void Square::SetHeight(double h){ Rectangle::SetHeight(h); Rectangle::SetWidth(h); } ---- End Of File:./rsl/square.cpp Автор статьи не без основания утверждает, что в приведенном примере в фукнции LSPV таки нарушается принцип подстановки: ---- File:./rsl/violation.cpp void LSPV(Rectangle& r){ r.SetWidth(5); r.SetHeight(4); assert(r.GetWidth() * r.GetHeight()) == 20); } ---- End Of File:./rsl/violation.cpp Можно было бы возразить автору, что принцип подстановки плохо сформулирован, что не определен термин замена (хотя в данном примере все понятно: в программу передается ссылка на объект подкласса), что непонятен термин поведение программы и так далее. Но попробуем проанализировать пример с точки зрения методов RDG [] и придать точный теоретико-множественный смысл этим и некоторым другим терминам.

Содержание раздела