# Liskov Substitution Principle (LSP)

The Liskov Substitution Principle states that objects of a superclass should be replaceable with objects of its subclasses without breaking the application.

LSP enforces something discussed so far: public inheritance should model an is-a relationship.

If class `B`

inherits from class `A`

: we can use pointers / references to `B`

objects in the place of pointers / references to `A`

objects: C++ gives us this.

Liskov Substitution is stronger: not only can we perform the substitution, but we should be able to do so at any place in the program, without affecting its correctness.

So precisely:

- If an invariance is true for class
`A`

, then it should also be true for class`B`

- If an invariant is true for method
`A::f`

, and`B`

overrides`f`

, then this invariant must be true for`B::f`

- If
`B::f`

overrides`A::f`

- If
`A::f`

has a precondition`P`

and a postcondition`Q`

, then`B::f`

should have a precondition`P'`

such that`P=>P'`

and a postcondition`Q'`

such that`Q'=>Q`

`B::f`

needs a*weaker*precondition and a*stronger*postcondition

- If

Ex: Contravariance problem

- Happens whenever we have a binary operator where the other parameter is the same type as
`*this`

.

As we’ve seen before, we must take in the same parameter when overriding. C++ enforces this, which actually enforces LSP for us.

- A
`Circle`

is-a`Shape`

- A
`Shape`

can be compared with other`Shape`

s - A
`Circle`

can be compared with any other`Shape`

To satisfy LSP, we must support comparison between different types of `Shape`

s.

` `

typeid`returns`

std::type_info` objects that can be compared.

`dynamic_cast`

: Is `other`

a `Circle`

, or a subclass of `Circle`

?
`typeid`

: Is `other`

exactly a `Circle`

?

typeid uses the dynamic-type so long as the class has at least one virtual method.

### Example of Violation of LSP

Ex: Is a `Square`

a `Rectangle`

?
4th Grader: Yes, a Square is a rectangle.

A square has all the properties of a rectangle.

What is the issue here?

we expect postcondition for

`Rectangle::setWith`

to be that the width is set and nothing else changes. But this is violated by our`Square`

class.

Violates LSP, does not satisfy an is-a relationship. Conclusion: Square are not Rectangles.

Possibility: Restructure inheritance hierarchy to make sure LSP is respected.

In general: how can we prevent LSP violations?

We should restrain what our subclasses can do, only allows them to customize what is truly necessary.

We can use a design pattern: Template Method Pattern, to make this process easier.