UP | HOME
2015-10-05 | ../../ | Slides

Liskov Substitution Principle (LSP)

Table of Contents

1 Abstract

Liskov Substitution Principle (LSP) is the L in SOLID Principles of OOD. It clarifies the meaning of inheritance beyond mere syntax. The principle applies to best practices in all OOP languages; certainly to: C++, Java, Scala, and Python. The clarification is crystal clear in the presence of pre- post conditions and class invariant.

[TBD double check use of S (now D) versus T (now B)]

2 Semantics of Inheritance

  1. If D is a derived type of B, Notation: D <: B, what are the must-have relationships between their methods?
  2. Regardless of whether our compilers can check these constraints.

2.1 Scenario #1

  1. A client class C1 is using D. Suppose we replace all occurrences of objects of D with those of B. No other changes are made in C1.
  2. What behavioral changes can we observe in C1?

2.2 Scenario #2

  1. (Reverse the roles of D and B.)
  2. A client class C2 is using B. Suppose we replace all occurrences of objects of B with those of D. No other changes are made in C2.
  3. What behavioral changes can we observe in C2?

2.3 Observations

  1. You should construct some examples, run, and observe.

2.4 Statements of Expectations

  1. "Derived types must be substitutable for base types." All OOP languages permit this. Even when d.m(x, y, z) has radically different behavior from b.m(x, y, z).
  2. "… derived class objects must be substitutable for the base class objects. That means objects of the derived class must behave in a manner consistent with the promises made in the base class' contract." [from C++ FAQ]
  3. "Functions that use pointers or references to base classes must be able to use objects of derived classes without knowing it."

2.5 Define "Behavior"

  1. Observable state:
    1. before entering the method (state as described by pre-condition),
    2. versus leaving the method (post condition)
  2. Public methods only
  3. Recall that pre- and post-conditions include the class invariant.

2.6 Origin of Expectations

  1. The expectations staed above are "best practices" to support software development life cycle, especially maintenance.
  2. Violating these expectations is bound to cause functional damage to the software.
  3. E.g., unit tests for the base class would never succeed for the subclass.

3 Proper Inheritance

  1. Background: ../Assertions
  2. Consider a public method m(x, y, z) of B and D.
  3. Preconditions must not be strengthened in a subtype.
    1. It should be the case that B.m.pre => D.m.pre
  4. Postconditions must not be weakened in a subtype.
    1. It should be the case that D.m.post => B.m.post
  5. Class Invariant B.cinv of the supertype B must be preserved in a subtype D.
    1. It should be the case that D.cinv => B.cinv

3.1 More

  1. OOD Open-Close Principle: Open for extension but Closed for modifications.
  2. If the above rules are not being held, re-design your inheritance details.

4 Dilemmas?

  1. Interface substitutability versus Behavior Equivalence

4.1 Circle a subtype of Ellipse?

  1. Let Ellipse1 have three public observer functions: major, minor, area. Circle1 has the same operations, but minor and major always return the radius.
  2. Let Ellipse2 have two more public setter functions, major(x), minor(x). Obviously, Circle2 has only major(x).

4.2 Colored Circle

  1. Circle c; ColoredCircle cc; c := cc; Problem?

4.3 Ellipse a subtype of Circle?

4.4 Specialization and Constratints

  1. We expect a subtype to be a specialization of a base type. The subtype also obeys some extra constraints that the base did not have.
  2. This works generally – but not always.

4.5 Answers

  1. Read the answers in Alistair Cockburn (in refs).

5 Liskov's Originals

  1. "If for each object s of type S there is an object t of type T such that for all programs P defined in terms of T, the behavior of P is unchanged when s is substituted for t then S is a subtype of T." [from Barbara Liskov, Data Abstraction and Hierarchy, SIGPLAN Notices, 23, 5, May 1988. Liskov won the Turing Award in 2008.]
  2. pmateti: The "behavior of P is unchanged" is too strong. Here is a restatement in a later paper:
  3. Let q(t) be a property (provable) about objects t of type T. Then q(s) should (provably) hold for objects s of type S where S is a subtype of T.
  4. pmateti: Provability is not the issue.
  5. pmateti: In the context of our OOPL, treat "type" as a synonym for "class".

6 References

  1. Liskov, Barbara H., and Jeannette M. Wing. "A behavioral notion of subtyping." ACM Transactions on Programming Languages and Systems (TOPLAS) 16.6 (1994): 1811-1841. http://www.cse.ohio-state.edu/~neelam/courses/788/lwb.pdf. Liskov won the Turing Award in 2008. Highly recommended Reading for CEG4180. Required Reading for CEG 7140.
  2. http://www.oodesign.com Recommended Visit.
  3. http://www.parashift.com/c++-faq/ Recommended Visit.
  4. Alistair Cockburn, http://alistair.cockburn.us/Constructive+deconstruction+of+subtyping A rigorous math logic based discussion of what subtypes are. Highly Recommended Reading.

Copyright © 2015 www.wright.edu/~pmateti 2015-10-05