1 / 15

LSP

LSP. Stéphane Ducasse --- 2005. A step deeper in Subtyping. Liskov Substitution Principle (LSP).

Download Presentation

LSP

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. LSP Stéphane Ducasse --- 2005

  2. A step deeper in Subtyping...

  3. Liskov Substitution Principle (LSP) • if for each object o1 of type S there is another 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. • Barbara Liskov, "Data Abstraction and Hierarchy," SIGPLAN Notices, 23,5 (May 1988)

  4. A Simple Bag • We will define a Bag as an object that accepts two messages: put and count • (send a-Bag 'put x) • puts an element x into the Bag, and • (send a-Bag 'count x) • gives the count of occurrences of x in the Bag (without changing a-Bag's state).

  5. A Simple Set • Likewise, a Set is defined as an object that accepts two messages: • (send a-Set 'put x) • puts an element x into a-Set unless it was already there, • (send a-Set 'count x) • gives the count of occurrences of x in a-Set (which is always either 0 or 1).

  6. A Bag Function • (define (fnb bag) • (send bag 'put 5) • (send bag 'put 5) • (send bag 'count 5)) • The behavior of this function can be summed as follows: given a Bag, the function adds two elements into it and returns • (+ 2 (send orig-bag 'count 5))

  7. The problem • Technically you can pass to fnb a Set object as well. Just as a Bag, a Set object accepts messages put and count. However applying fnb to a Set object will break the function's post-condition • Therefore, passing a set object where a bag was expected changes behavior of some program. According to the Liskov Substitution Principle (LSP), a Set is not substitutable for a Bag -- a Set cannot be a subtype of a Bag.

  8. Another function • (define (fns set) • (send set 'put 5) • (send set 'count 5)) • The behavior of this function is: given a Set, the function adds an element into it and returns 1.

  9. Problem two • If you pass to this function a bag (which -- just as a set -- replies to messages put and count), the function fnsmay return a number greater than 1. This will break fns's contract, which promised always to return 1.

  10. Finally • Therefore, from the OO point of view, neither a Bag nor a Set are a subtype of the other. • Bag and Set only appear similar. The interface or an implementation of a Bag and a Set appear to invite subclassing of a Set from a Bag (or vice versa). Doing so however will violate the LSP -- and you have to brace for very subtle errors. • Sets and Bags are very simple types, far simpler than the ones you deal with in a production code. either. It's manual work -- you have to see the problem

  11. Watch out • Alas, LSP when considered from an OOP point of view is undecidable. • You cannot count on a compiler for help in pointing out an error. You cannot rely on regression tests

  12. In C++ • typedef int const * CollIterator;// Primitive but will do • class CBag { • public: • int size(void) const;// The number of elements in the bag • virtual void put(const int elem);// Put an element into the bag • int count(const int elem) const;// Count the number of occurrences • // of a particular element in the bag • virtual bool del(const int elem); // Remove an element from the bag • // Return false if the element • // didn't exist • CollIterator begin(void) const;// Standard enumerator interface • CollIterator end(void) const; • CBag(void); • virtual CBag * clone(void) const;// Make a copy of the bag • private: • // implementation details elided • };

  13. CSet • class CSet : public CBag { • public: • bool memberof(const int elem) const { return count(elem) > 0; } • // Overriding of CBag::put • void put(const int elem) • { if(!memberof(elem)) CBag::put(elem); } • CSet * clone(void) const • { CSet * new_set = new CSet(); *new_set += *this; return new_set; } • CSet(void) {} • };

  14. Summary • Subtyping...

More Related