Lsp stéphane Ducasse 2005

Yüklə 0,5 Mb.
ölçüsü0,5 Mb.


  • Stéphane Ducasse --- 2005

A step deeper in Subtyping...

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)

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).

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).

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))

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.

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.

Problem two

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


  • 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

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

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

  • };


  • 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) {}

  • };


  • Subtyping...

Yüklə 0,5 Mb.

Dostları ilə paylaş:

Verilənlər bazası müəlliflik hüququ ilə müdafiə olunur © 2023
rəhbərliyinə müraciət

    Ana səhifə