#### [SOLVED] What is an example of the Liskov Substitution Principle?

I have heard that the Liskov Substitution Principle (LSP) is a fundamental principle of object oriented design. What is it and what are some examples of its use?

#### @Ivan Porta 2020-03-02 17:54:24

This principle was introduced by Barbara Liskov in 1987 and extends the Open-Closed Principle by focusing on the behavior of a superclass and its subtypes.

Its importance becomes obvious when we consider the consequences of violating it. Consider an application that uses the following class.

``````public class Rectangle
{
private double width;

private double height;

public double Width
{
get
{
return width;
}
set
{
width = value;
}
}

public double Height
{
get
{
return height;
}
set
{
height = value;
}
}
}
``````

Imagine that one day, the client demands the ability to manipulate squares in addition to rectangles. Since a square is a rectangle, the square class should be derived from the Rectangle class.

``````public class Square : Rectangle
{
}
``````

However, by doing that we will encounter two problems:

A square does not need both height and width variables inherited from the rectangle and this could create a significant waste in memory if we have to create hundreds of thousands of square objects. The width and height setter properties inherited from the rectangle are inappropriate for a square since the width and height of a square are identical. In order to set both height and width to the same value, we can create two new properties as follows:

``````public class Square : Rectangle
{
public double SetWidth
{
set
{
base.Width = value;
base.Height = value;
}
}

public double SetHeight
{
set
{
base.Height = value;
base.Width = value;
}
}
}
``````

Now, when someone will set the width of a square object, its height will change accordingly and vice-versa.

``````Square s = new Square();
s.SetWidth(1); // Sets width and height to 1.
s.SetHeight(2); // sets width and height to 2.
``````

Let's move forward and consider this other function:

``````public void A(Rectangle r)
{
r.SetWidth(32); // calls Rectangle.SetWidth
}
``````

If we pass a reference to a square object into this function, we would violate the LSP because the function does not work for derivatives of its arguments. The properties width and height aren't polymorphic because they aren't declared virtual in rectangle (the square object will be corrupted because the height won't be changed).

However, by declaring the setter properties to be virtual we will face another violation, the OCP. In fact, the creation of a derived class square is causing changes to the base class rectangle.

#### @johannesMatevosyan 2020-01-24 12:19:38

The LSP in simple terms states that objects of the same superclass should be able to be swapped with each other without breaking anything.

For example, if we have a `Cat` and a `Dog` class derived from an `Animal` class, any functions using the Animal class should be able to use `Cat` or `Dog` and behave normally.

#### @Rahamath 2019-08-19 11:55:07

The Liskov Substitution Principle

• The overridden method shouldn’t remain empty
• The overridden method shouldn’t throw an error
• Base class or interface behavior should not go for modification (rework) as because of derived class behaviors.

#### @m-sharp 2009-02-25 04:44:31

A great example illustrating LSP (given by Uncle Bob in a podcast I heard recently) was how sometimes something that sounds right in natural language doesn't quite work in code.

In mathematics, a `Square` is a `Rectangle`. Indeed it is a specialization of a rectangle. The "is a" makes you want to model this with inheritance. However if in code you made `Square` derive from `Rectangle`, then a `Square` should be usable anywhere you expect a `Rectangle`. This makes for some strange behavior.

Imagine you had `SetWidth` and `SetHeight` methods on your `Rectangle` base class; this seems perfectly logical. However if your `Rectangle` reference pointed to a `Square`, then `SetWidth` and `SetHeight` doesn't make sense because setting one would change the other to match it. In this case `Square` fails the Liskov Substitution Test with `Rectangle` and the abstraction of having `Square` inherit from `Rectangle` is a bad one.

Y'all should check out the other priceless SOLID Principles Motivational Posters.

#### @Pacerier 2012-04-26 19:28:38

@m-sharp What if it's an immutable Rectangle such that instead of SetWidth and SetHeight, we have the methods GetWidth and GetHeight instead?

#### @Sklivvz 2012-05-19 21:43:28

Moral of the story: model your classes based on behaviours not on properties; model your data based on properties and not on behaviours. If it behaves like a duck, it's certainly a bird.

#### @SteveT 2012-09-24 15:46:25

Well, a square clearly IS a type of rectangle in the real world. Whether we can model this in our code depends on the spec. What the LSP indicates is that subtype behavior should match base type behavior as defined in the base type specification. If the rectangle base type spec says that height and width can be set independently, then LSP says that square cannot be a subtype of rectangle. If the rectangle spec says that a rectangle is immutable, then a square can be a subtype of rectangle. It's all about subtypes maintaining the behavior specified for the base type.

#### @asmeurer 2013-01-20 06:13:21

@Pacerier there is no issue if it's immutable. The real issue here is that we are not modeling rectangles, but rather "reshapable rectangles," i.e., rectangles whose width or height can be modified after creation (and we still consider it to be the same object). If we look at the rectangle class in this way, it is clear that a square is not a "reshapable rectangle", because a square cannot be reshaped and still be a square (in general). Mathematically, we don't see the problem because mutability doesn't even make sense in a mathematical context.

#### @ruhong 2015-02-04 06:09:01

From Prof Barbara Liskov's lecture: "Objects of subtypes should behave like those of supertypes if used via supertype methods."

#### @brighty 2015-02-10 10:53:40

If width and height can be altered by setters, there should be just a rectangle class and no special square class. Instead, the rectangle class should have a getter that is named IsSquare. Whenever width and height have the same values, IsSquare will return true, otherwise false. Types are not always static, but sometimes - like in this case - can change.

#### @jungle_mole 2015-09-11 05:03:28

so why i even need subtyping if my inherited class's behaviour doesn't differ from parent (excluding cases, when it does the same but different way)? why one need all those override methods if they have to behave absolutely similarly to base's? speaking of geometry figures: IDrawable has Draw(). how could you insist Circle:IDrawable's Draw() give the same result as Square:IDrawable's? or, say, Rotated90DegreesSquare:Square draw the same as square?

#### @MC Emperor 2015-10-28 00:45:59

I have one question about the principle. Why would be the problem if `Square.setWidth(int width)` was implemented like this: `this.width = width; this.height = width;`? In this case it is guaranteed that the width equals the height.

#### @David Tonhofer 2016-01-05 15:49:48

That Motivational Poster makes no sense. It should be "If it looks like a Duck, Quacks Like a Duck, But Needs Batteries ... why are you interested in the Batteries, again?" Because in the end it implies that the only substitution for a duck is another duck (best the exact same one). Such radicalism is self-defeating.

#### @mbx 2016-03-02 07:42:18

The Square-Rectangle Problem is also known as Circle-Ellipse Problem.

#### @Sudhir 2016-05-23 12:42:06

The right or wrong, good or bad, depends on one's perspective - whether it is from code consumer side or from the code author side. LSP, IMO, applies to the consumer side. Put in right perspective, many wrongs look right.

#### @Ed L 2016-07-16 01:23:15

Another solution is to define rectangles as aspect-ratio preserving rather than as having independent widths and heights.

#### @iheanyi 2016-08-12 17:58:03

Seems to not answer the question. After reading it, I still don't know what LSP is (unless the poster contains the definition, though given the context of such posters, this is not clear).

#### @iheanyi 2016-08-12 18:03:41

I also don't get the square example. How does setWidth and setHeight not "make sense" on a square. As you very easily explained, doing one implies the other - that's just the definition of a square. It doesn't explain why there is something wrong or inconsistent with substituting a square for a rectangle.

#### @Ungeheuer 2016-11-22 05:48:05

Couldn't you simply override setWidth or setHeight, and in the definition call the other method with the same parameter and poof, it all works and behaviour is consistent?

#### @sdlins 2016-12-26 03:12:06

@MCEmperor if you change the implementation of `setHeight()` and `setWidth()` in the `Square`, so the places in your code where you use a `Rectangule` would not work anymore if you pass a `Square` and this is the main point about LSP;

#### @BKSpurgeon 2017-01-02 13:30:58

Thank you for your answer - but so what if the LSP is broken?

#### @AnT 2017-01-28 01:57:28

However, the picture is NOT a valid example of a broken LSP (smells of Reddit actually, and that is not something we want to smell here on SO). Subclasses will always be more specific than superclasses. However, their specifics do not necessarily break LSP. It is a question of whether these specifics affect (and break) the common contract. Whether a battery-powered duck breaks the common contract of an abstract duck depends on the specific details of the design.

#### @johnny 5 2017-02-28 22:41:12

Everyone uses this square vs rectangle which such a horrible example. You're overriding the Width Property to set the Height Property, Which seems more like side effect. This would all be solved if you made people explicitly set the width and height.

#### @PaulB 2017-06-05 10:59:28

Both image and link at the end are broken. Do you mind fixing it?

#### @m-sharp 2017-06-06 10:13:13

Thanks @PaulB. Fixed it.

#### @Palec 2017-06-07 12:39:30

Los techies are working for me now, @m-sharp. Was it just temporary outage, or maybe even regional? Revision 8 seems at least unneccessary, now.

#### @m-sharp 2017-06-07 14:12:46

Cool. Rolled back the change. SO has a really nice revision history!

#### @Palec 2017-06-10 18:42:39

Damn, the whole Lot Techies site now returns the same page titled "Database Error" and containing only a `h1` with "Error establishing a database connection". I found the latest WayBack Machine snapshot and it clearly says that the images are licensed under CC BY-SA. I suggest you link to the WayBack Machine snapshot as well as the original URL and upload the image to Stack Overflow's servers (via the editor). Thus, outages will not affect the post.

#### @inf3rno 2017-10-09 03:48:29

The `o.setDimensions(width, height)` would solve that problem, but LSP still would be violated, because a square has stronger preconditions (`width == height`) than a rectangle. I don't think your post answers anything about LSP.

#### @BrunoLM 2017-10-21 10:06:50

There is a good complementary information about method override / contracts here softwareengineering.stackexchange.com/a/244783/1451

#### @ATL_DEV 2017-12-15 20:33:51

Is a rectangle a type of square or is a square a type of rectangle or the other way around? A rectangle can be defined as a square with unequal sides and a square can be defined as a rectangle with equal sides. A square with unequal sides is not a square, but a rectangle with equal sides is still a rectangle and a square. So a square is a rectangle with an additional contract. Therefore, the interface for a square should be the same as one for a rectangle. Setting one dimension should set the other makes perfect sense.

#### @AustinWBryan 2018-05-08 23:45:41

I wouldn't say there's no issue if they're immuatable. It could throw a reader off to see `GetHeight` and `GetWidth` if they're going to do the exact same thing. That might by a tiny issue, but still a reason to do it another way.

#### @anilkay 2018-06-17 11:25:54

İs it calls %100 rule in some books?

#### @Ben Kushigian 2018-06-19 19:18:07

@AustinWBryan no, these are well defined quantities. A square has both a height and a width; they happen to be equal. If the reader is thrown off by this then they either learn something new and important about the code or they don't belong there :)

#### @Mircea Ion 2019-02-05 03:17:17

I think that we are confusing sub-type with "particular case". A square has nothing different in behavior compared with a rectangle. The perimeter, area can be calculated using the same formulas. Square is not an improvement or refinement of a rectangle, it's just a particular case. Square shouldn't be a subclass of a rectangle, it shouldn't even be a separate class.

#### @alancalvitti 2019-03-29 16:16:35

@MirceaIon, Square could be a subclass of Rectangle to simplify the interface, eg with `SetLength` which could internally call `SetWidth` and `SetHeight`

#### @Alex 2019-04-17 16:45:07

Its OK to derive Square from Rectangle, but you should not have setWidth and setHeight in the case. But no one could prevent you to have setters for a zone there you put the rectangles. In the case, Square will fill only part of the zone, while Rectangle will fill it completely. :)

#### @Saurabh Goyal 2019-06-11 15:50:28

Can someone please, for the love of code, tell me how else to model this same example then so that it follows LSP?

#### @Aleksei Guzev 2019-12-15 12:38:46

Once I have failed an interview on this exact question about squares. The interviewer rejected my immediate question: "What are we going to do with those rectangles and squares?" Today I'm happy I hadn't got that job. :)

#### @Yousha Aleayoub 2020-02-05 16:18:27

Which uncle Bob? :-?

#### @Murilo 2020-04-09 01:40:48

@sdlins I disagree. Can you name one situation where if you have the behavior of setHeight and setWidth overwritten in the Square class like MCEmperor signed that the code would not work for Reactangle anymore?

#### @Steve Chamaillard 2018-02-18 19:07:29

I see rectangles and squares in every answer, and how to violate the LSP.

I'd like to show how the LSP can be conformed to with a real-world example :

``````<?php

interface Database
{
public function selectQuery(string \$sql): array;
}

class SQLiteDatabase implements Database
{
public function selectQuery(string \$sql): array
{
// sqlite specific code

return \$result;
}
}

class MySQLDatabase implements Database
{
public function selectQuery(string \$sql): array
{
// mysql specific code

return \$result;
}
}
``````

This design conforms to the LSP because the behaviour remains unchanged regardless of the implementation we choose to use.

And yes, you can violate LSP in this configuration doing one simple change like so :

``````<?php

interface Database
{
public function selectQuery(string \$sql): array;
}

class SQLiteDatabase implements Database
{
public function selectQuery(string \$sql): array
{
// sqlite specific code

return \$result;
}
}

class MySQLDatabase implements Database
{
public function selectQuery(string \$sql): array
{
// mysql specific code

return ['result' => \$result]; // This violates LSP !
}
}
``````

Now the subtypes cannot be used the same way since they don't produce the same result anymore.

#### @Palec 2018-02-25 13:02:44

The example does not violate LSP only as long as we constrain the semantics of `Database::selectQuery` to support just the subset of SQL supported by all DB engines. That's hardly practical... That said, the example is still easier to grasp than most others used here.

I found this answer the easiest to grasp out of the rest.

Let me try, consider an interface:

``````interface Planet{
}
``````

This is implemented by class:

``````class Earth implements Planet {
}
}
``````

You will use Earth as:

``````\$planet = new Earth(6371);
\$calc = new SurfaceAreaCalculator(\$planet);
\$calc->output();
``````

Now consider one more class which extends Earth:

``````class LiveablePlanet extends Earth{
public function color(){
}
}
``````

Now according to LSP, you should be able to use LiveablePlanet in place of Earth and it should not break your system. Like:

``````\$planet = new LiveablePlanet(6371);  // Earlier we were using Earth here
\$calc = new SurfaceAreaCalculator(\$planet);
\$calc->output();
``````

Examples taken from here

#### @zar 2019-05-03 15:46:33

Poor example. `Earth` is an instance of `plant`, why would it get derived from it?

#### @Zahra.HY 2019-04-06 12:55:40

LSP says that ''Objects should be replaceable by their subtypes''. On the other hand, this principle points to

Child classes should never break the parent class`s type definitions.

and the following example helps to have a better understanding of LSP.

Without LSP:

``````public interface CustomerLayout{

public void render();
}

public FreeCustomer implements CustomerLayout {
...
@Override
public void render(){
//code
}
}

...
@Override
public void render(){
return; //it isn`t rendered in this case
//code
}
}

public void renderView(CustomerLayout layout){
layout.render();
}
``````

Fixing by LSP:

``````public interface CustomerLayout{
public void render();
}

public FreeCustomer implements CustomerLayout {
...
@Override
public void render(){
//code
}
}

...
@Override
public void render(){
showAd();//it has a specific behavior based on its requirement
//code
}
}

public void renderView(CustomerLayout layout){
layout.render();
}
``````

#### @Khaled Qasem 2019-02-10 10:56:06

Let’s illustrate in Java:

``````class TrasportationDevice
{
String name;
String getName() { ... }
void setName(String n) { ... }

double speed;
double getSpeed() { ... }
void setSpeed(double d) { ... }

Engine engine;
Engine getEngine() { ... }
void setEngine(Engine e) { ... }

void startEngine() { ... }
}

class Car extends TransportationDevice
{
@Override
void startEngine() { ... }
}
``````

There is no problem here, right? A car is definitely a transportation device, and here we can see that it overrides the startEngine() method of its superclass.

``````class Bicycle extends TransportationDevice
{
@Override
void startEngine() /*problem!*/
}
``````

Everything isn’t going as planned now! Yes, a bicycle is a transportation device, however, it does not have an engine and hence, the method startEngine() cannot be implemented.

These are the kinds of problems that violation of Liskov Substitution Principle leads to, and they can most usually be recognized by a method that does nothing, or even can’t be implemented.

The solution to these problems is a correct inheritance hierarchy, and in our case we would solve the problem by differentiating classes of transportation devices with and without engines. Even though a bicycle is a transportation device, it doesn’t have an engine. In this example our definition of transportation device is wrong. It should not have an engine.

We can refactor our TransportationDevice class as follows:

``````class TrasportationDevice
{
String name;
String getName() { ... }
void setName(String n) { ... }

double speed;
double getSpeed() { ... }
void setSpeed(double d) { ... }
}
``````

Now we can extend TransportationDevice for non-motorized devices.

``````class DevicesWithoutEngines extends TransportationDevice
{
void startMoving() { ... }
}
``````

And extend TransportationDevice for motorized devices. Here is is more appropriate to add the Engine object.

``````class DevicesWithEngines extends TransportationDevice
{
Engine engine;
Engine getEngine() { ... }
void setEngine(Engine e) { ... }

void startEngine() { ... }
}
``````

Thus our Car class becomes more specialized, while adhering to the Liskov Substitution Principle.

``````class Car extends DevicesWithEngines
{
@Override
void startEngine() { ... }
}
``````

And our Bicycle class is also in compliance with the Liskov Substitution Principle.

``````class Bicycle extends DevicesWithoutEngines
{
@Override
void startMoving() { ... }
}
``````

#### @Lukas Lukac 2017-10-28 23:10:45

Long story short, let's leave rectangles rectangles and squares squares, practical example when extending a parent class, you have to either PRESERVE the exact parent API or to EXTEND IT.

Let's say you have a base ItemsRepository.

``````class ItemsRepository
{
/**
* @return int Returns number of deleted rows
*/
public function delete()
{
// perform a delete query
\$numberOfDeletedRows = 10;

return \$numberOfDeletedRows;
}
}
``````

And a sub class extending it:

``````class BadlyExtendedItemsRepository extends ItemsRepository
{
/**
* @return void Was suppose to return an INT like parent, but did not, breaks LSP
*/
public function delete()
{
// perform a delete query
\$numberOfDeletedRows = 10;

// we broke the behaviour of the parent class
return;
}
}
``````

Then you could have a Client working with the Base ItemsRepository API and relying on it.

``````/**
* Class ItemsService is a client for public ItemsRepository "API" (the public delete method).
*
* Technically, I am able to pass into a constructor a sub-class of the ItemsRepository
* but if the sub-class won't abide the base class API, the client will get broken.
*/
class ItemsService
{
/**
* @var ItemsRepository
*/
private \$itemsRepository;

/**
* @param ItemsRepository \$itemsRepository
*/
public function __construct(ItemsRepository \$itemsRepository)
{
\$this->itemsRepository = \$itemsRepository;
}

/**
* !!! Notice how this is suppose to return an int. My clients expect it based on the
* ItemsRepository API in the constructor !!!
*
* @return int
*/
public function delete()
{
return \$this->itemsRepository->delete();
}
}
``````

The LSP is broken when substituting parent class with a sub class breaks the API's contract.

``````class ItemsController
{
/**
* Valid delete action when using the base class.
*/
public function validDeleteAction()
{
\$itemsService = new ItemsService(new ItemsRepository());
\$numberOfDeletedItems = \$itemsService->delete();

// \$numberOfDeletedItems is an INT :)
}

/**
* Invalid delete action when using a subclass.
*/
public function brokenDeleteAction()
{
\$numberOfDeletedItems = \$itemsService->delete();

// \$numberOfDeletedItems is a NULL :(
}
}
``````

#### @Maysara Alhindi 2017-07-04 19:58:38

Substitutability is a principle in object-oriented programming stating that, in a computer program, if S is a subtype of T, then objects of type T may be replaced with objects of type S

let's do a simple example in Java:

``````public class Bird{
public void fly(){}
}
public class Duck extends Bird{}
``````

``````public class Ostrich extends Bird{}
``````

Ostrich is a bird, But it can't fly, Ostrich class is a subtype of class Bird, But it can't use the fly method, that means that we are breaking LSP principle.

## Good example

``````public class Bird{
}
public class FlyingBirds extends Bird{
public void fly(){}
}
public class Duck extends FlyingBirds{}
public class Ostrich extends Bird{}
``````

#### @Moody 2017-11-20 01:05:06

Nice example, but what would you do if the client has `Bird bird`. You have to cast the object to FlyingBirds to make use of fly, which isn't nice right?

#### @Steve Chamaillard 2018-02-18 18:56:35

No. If the client has `Bird bird`, that means it cannot use `fly()`. That's it. Passing a `Duck` does not change this fact. If the client has `FlyingBirds bird`, then even if it gets passed a `Duck` it should always work the same way.

#### @Saharsh 2019-03-05 18:50:05

Wouldn't this also serve as a good example for Interface Segregation?

Excellent example Thanks Man

#### @Thirdy 2019-05-28 12:32:41

How about using Interface 'Flyable' (can't think of a better name). This way we don't commit ourselves into this rigid hierarchy.. Unless we know really need it.

#### @Sławomir Lenart 2020-01-31 18:57:50

Vet which cures broken wings will see a Bad example like a better one. Some flightless bird species can fly their own way (chicken is a hybrid here). Also flying ability changes in evolution. A default NULL-able fly method is a good decision, to be overridden later.

#### @Ari 2020-02-25 15:29:57

So, the parent class should only include the behaviors that its entire children have or in other words, not limiting its children behaviors.

Here is an excerpt from this post that clarifies things nicely:

[..] in order to comprehend some principles, it’s important to realize when it’s been violated. This is what I will do now.

What does the violation of this principle mean? It implies that an object doesn’t fulfill the contract imposed by an abstraction expressed with an interface. In other words, it means that you identified your abstractions wrong.

Consider the following example:

``````interface Account
{
/**
* Withdraw \$money amount from this account.
*
* @param Money \$money
* @return mixed
*/
public function withdraw(Money \$money);
}
class DefaultAccount implements Account
{
private \$balance;
public function withdraw(Money \$money)
{
if (!\$this->enoughMoney(\$money)) {
return;
}
\$this->balance->subtract(\$money);
}
}
``````

Is this a violation of LSP? Yes. This is because the account’s contract tells us that an account would be withdrawn, but this is not always the case. So, what should I do in order to fix it? I just modify the contract:

``````interface Account
{
/**
* Withdraw \$money amount from this account if its balance is enough.
* Otherwise do nothing.
*
* @param Money \$money
* @return mixed
*/
public function withdraw(Money \$money);
}
``````

Voilà, now the contract is satisfied.

This subtle violation often imposes a client with the ability to tell the difference between concrete objects employed. For example, given the first Account’s contract, it could look like the following:

``````class Client
{
public function go(Account \$account, Money \$money)
{
if (\$account instanceof DefaultAccount && !\$account->hasEnoughMoney(\$money)) {
return;
}
\$account->withdraw(\$money);
}
}
``````

And, this automatically violates the open-closed principle [that is, for money withdrawal requirement. Because you never know what happens if an object violating the contract doesn't have enough money. Probably it just returns nothing, probably an exception will be thrown. So you have to check if it `hasEnoughMoney()` -- which is not part of an interface. So this forced concrete-class-dependent check is an OCP violation].

This point also addresses a misconception that I encounter quite often about LSP violation. It says the “if a parent’s behavior changed in a child, then, it violates LSP.” However, it doesn’t — as long as a child doesn’t violate its parent’s contract.

#### @GauRang Omar 2018-05-21 09:01:48

Liskov's Substitution Principle(LSP)

All the time we design a program module and we create some class hierarchies. Then we extend some classes creating some derived classes.

We must make sure that the new derived classes just extend without replacing the functionality of old classes. Otherwise, the new classes can produce undesired effects when they are used in existing program modules.

Liskov's Substitution Principle states that if a program module is using a Base class, then the reference to the Base class can be replaced with a Derived class without affecting the functionality of the program module.

Example:

Below is the classic example for which the Liskov's Substitution Principle is violated. In the example, 2 classes are used: Rectangle and Square. Let's assume that the Rectangle object is used somewhere in the application. We extend the application and add the Square class. The square class is returned by a factory pattern, based on some conditions and we don't know the exact what type of object will be returned. But we know it's a Rectangle. We get the rectangle object, set the width to 5 and height to 10 and get the area. For a rectangle with width 5 and height 10, the area should be 50. Instead, the result will be 100

``````    // Violation of Likov's Substitution Principle
class Rectangle {
protected int m_width;
protected int m_height;

public void setWidth(int width) {
m_width = width;
}

public void setHeight(int height) {
m_height = height;
}

public int getWidth() {
return m_width;
}

public int getHeight() {
return m_height;
}

public int getArea() {
return m_width * m_height;
}
}

class Square extends Rectangle {
public void setWidth(int width) {
m_width = width;
m_height = width;
}

public void setHeight(int height) {
m_width = height;
m_height = height;
}

}

class LspTest {
private static Rectangle getNewRectangle() {
// it can be an object returned by some factory ...
return new Square();
}

public static void main(String args[]) {
Rectangle r = LspTest.getNewRectangle();

r.setWidth(5);
r.setHeight(10);
// user knows that r it's a rectangle.
// It assumes that he's able to set the width and height as for the base
// class

System.out.println(r.getArea());
// now he's surprised to see that the area is 100 instead of 50.
}
}
``````

Conclusion:

This principle is just an extension of the Open Close Principle and it means that we must make sure that new derived classes are extending the base classes without changing their behavior.

Some similar concepts for better structure: Convention over configuration

LSP concerns invariants.

The classic example is given by the following pseudo-code declaration (implementations omitted):

``````class Rectangle {
int getHeight()
void setHeight(int value)
int getWidth()
void setWidth(int value)
}

class Square : Rectangle { }
``````

Now we have a problem although the interface matches. The reason is that we have violated invariants stemming from the mathematical definition of squares and rectangles. The way getters and setters work, a `Rectangle` should satisfy the following invariant:

``````void invariant(Rectangle r) {
r.setHeight(200)
r.setWidth(100)
assert(r.getHeight() == 200 and r.getWidth() == 100)
}
``````

However, this invariant must be violated by a correct implementation of `Square`, therefore it is not a valid substitute of `Rectangle`.

#### @DrPizza 2009-11-30 06:54:01

And hence the difficulty of using "OO" to model anything we might want to actually model.

@DrPizza: Absolutely. However, two things. Firstly, such relationships can still be modelled in OOP, albeit incompletely or using more complex detours (pick whichever suits your problem). Secondly, there’s no better alternative. Other mappings/modellings have the same or similar problems. ;-)

#### @ca9163d9 2012-01-23 20:10:26

@KonradRudolph, It's a good example. What's the right way to declare `Square` then?

@NickW In some cases (but not in the above) you can simply invert the inheritance chain – logically speaking, a 2D point is-a 3D point, where the third dimension is disregarded (or 0 – all points lie on the same plane in 3D space). But this is of course not really practical. In general, this is one of the cases where inheritance doesn’t really help, and no natural relationship exists between the entities. Model them separately (at least I don’t know of a better way).

#### @Sklivvz 2012-05-19 21:47:45

OOP is meant to model behaviours and not data. Your classes violate encapsulation even before violating LSP.

@Sklivvz I agree. It was hard to come up with a concise example though, and this one is the stock LSP example (you’ll find it in several books). But yes, while common, this is far from good OOP.

#### @Leonid 2012-07-03 16:50:40

The `setHeight()` and `setWidth()` methods probably should not be allowed to exist because that makes a class mutable. However, should they exist, one could just `throw NotSupportedException() / NotImplementedException()` or something similar.

@Leonid In a way, that also breaks the contract since it changes the “signature” (i.e. the possible ways in which the function can exit). Now, some frameworks (ahem .NET …) routinely use this route but I consider it very bad interface design.

#### @nurabha 2013-06-05 18:31:48

I dont understand how ls LSP violated here. The invariant states that the getheight and getwidth should return the set height and set width which is always true regardless of weather rectangle is square or rectangle. If client sets different height and width, surely he knows the object is a not a square. Similarly, if client knew the object is square, he will set equal heigh and width. Assuming rectangle class had two functions area and perimeter, the functions would work properly whether rectangle is a square or not. Then how is this violating LSP ?

@nurabha “which is always true regardless of weather rectangle is square or rectangle” – false. With a properly coded `square` this will not always true, both setters need to reset both width and height, otherwise they won’t preserve the (implied) invariants of a square. In other words: you have an inconsistent type system, and you never want that.

#### @Wolfzoon 2016-08-07 17:41:05

@nurabha "Assuming rectangle had two functions area and perimeter" would lead to the same problem. `SetArea(4); SetPerimeter(10);` would make a regular rectangle model a 1x4 rectangle. The calls would make a `Square` class model first a 2x2, and then either change to a sqrt(10)xsqrt(10) square or throw an `InvalidOperationException` or something.

#### @iheanyi 2016-08-12 18:15:39

If there aren't actual invariants, how can you have violated them? How does one know what variants exist to be violated (or conformed)?

@iheanyi You either need to make invariants explicit (aka. assertions, or using the type system) or you need to know the domain you’re working in. We know how rectangles and squares are defined, so we know what invariants they impose.

#### @iheanyi 2016-08-13 21:35:28

I agree - either the constraints or invariants should be explicit, or they should be forced upon you by the system. But, based on your example, there is nothing forcing me to write a square class with the "implied" invariant you mentioned. I suppose I'd suggest updating your answer to remove "implied" when discussing the invariants, they are actual constraints that give rise to the problem.

#### @Paulustrious 2017-08-05 15:00:23

LSP should not know what the derived object does, just that derived objects honour the base class contract. For example Square can have `SetDepth(int d) => throw exception`. But I wonder...is a rectangle a special type of square that doesn't demand H=W? Alternatively..Quadrilateral ⇒ Trapezoid ⇒ Parallelogram.

#### @Paulustrious 2017-08-05 15:14:30

Alternatively..`Quadrilateral ⇒ Trapezoid ⇒ Parallelogram`. Rectangle and Square will ultimately derive. from Parallelogram, although there would be Parallelogram ⇒ Rhombus ⇒ Square. Getting your derivations right is like designing database tables. Get it wrong at the start and you are heading for a screw-up

#### @AustinWBryan 2018-05-08 23:54:32

Would it make more sense for a Rectangle to inherit from a type of Square, or to have Square and Rectangle just be sibling classes?

@AustinWBryan You’d avoid this particular issue but the relationship doesn’t really make sense: inheritance models “is-a” relationships and “every rectangle is-a square” is wrong (and, as a consequence, you would run into other issues where you can’t simply replace one for the other). It’s correct the other way round (“every square is-a rectangle”), which is why it’s so tempting to write code that violates LSP.

#### @AustinWBryan 2018-05-09 16:35:46

@KonradRudolph So then would it be better to keep them as sibling classes that inherit from `Shape` or `Parallelogram` or something?

@AustinWBryan Yep; the longer I’ve been working in this field, the more I tend to use inheritance for interfaces and abstract base classes only, and composition for the rest. It’s sometimes a bit more work (typing wise) but it avoids a whole bunch of problems, and is widely echoed advice by other experienced programmers.

#### @AustinWBryan 2018-05-09 16:47:55

@KonradRudolph Wow, I had no idea, though, on my last project, I did experience the problems of using too much inheritance. I realized I wanted to give some derived classes the properties of other derived classes, and there was no way to do that. Do you think only abstract classes should have children, for the most part?

@AustinWBryan For the most part, yes. It’s famously one of the rules of the influential Effective C++ books, and a more general rule, Composition over Inheritance, has its own Wikipedia page.

#### @AustinWBryan 2018-05-09 20:59:30

@KonradRudolph Wow, thanks, I'll check this out. Is that book still worth a read for C# development, to learn structures and design patterns?

@AustinWBryan Probably not, unfortunately; it’s very specific to C++. Bill Wagner’s Effective C# follows a similar pattern though.

#### @Reuel Ribeiro 2019-01-11 16:35:09

@ca9163d9 For modeling the `Square` from a `Rectangle`, if a polymorphic approach is not a must, I would advocate for a `SquareDecorator` which takes the `Rectangle` object. What you or anybody else think of that?

@ReuelRibeiro This goes into the direction of over-engineering; most of the time it would be better to simply provide orthogonal classes that might both inherit from a `Shape`. That said, your approach is certainly the correct solution in many real-life use-cases.

#### @inf3rno 2017-10-09 04:26:28

Let's say we use a rectangle in our code

``````r = new Rectangle();
// ...
r.setDimensions(1,2);
r.fill(colors.red());
canvas.draw(r);
``````

In our geometry class we learned that a square is a special type of rectangle because its width is the same length as its height. Let's make a `Square` class as well based on this info:

``````class Square extends Rectangle {
setDimensions(width, height){
assert(width == height);
super.setDimensions(width, height);
}
}
``````

If we replace the `Rectangle` with `Square` in our first code, then it will break:

``````r = new Square();
// ...
r.setDimensions(1,2); // assertion width == height failed
r.fill(colors.red());
canvas.draw(r);
``````

This is because the `Square` has a new precondition we did not have in the `Rectangle` class: `width == height`. According to LSP the `Rectangle` instances should be substitutable with `Rectangle` subclass instances. This is because these instances pass the type check for `Rectangle` instances and so they will cause unexpected errors in your code.

This was an example for the "preconditions cannot be strengthened in a subtype" part in the wiki article. So to sum up, violating LSP will probably cause errors in your code at some point.

#### @Ishan Aggarwal 2017-09-23 19:26:00

Likov's Substitution Principle states that if a program module is using a Base class, then the reference to the Base class can be replaced with a Derived class without affecting the functionality of the program module.

Intent - Derived types must be completely substitute able for their base types.

Example - Co-variant return types in java.

#### @Phillip Wells 2008-09-12 13:34:37

Robert Martin has an excellent paper on the Liskov Substitution Principle. It discusses subtle and not-so-subtle ways in which the principle may be violated.

Some relevant parts of the paper (note that the second example is heavily condensed):

# A Simple Example of a Violation of LSP

One of the most glaring violations of this principle is the use of C++ Run-Time Type Information (RTTI) to select a function based upon the type of an object. i.e.:

``````void DrawShape(const Shape& s)
{
if (typeid(s) == typeid(Square))
DrawSquare(static_cast<Square&>(s));
else if (typeid(s) == typeid(Circle))
DrawCircle(static_cast<Circle&>(s));
}
``````

Clearly the `DrawShape` function is badly formed. It must know about every possible derivative of the `Shape` class, and it must be changed whenever new derivatives of `Shape` are created. Indeed, many view the structure of this function as anathema to Object Oriented Design.

# Square and Rectangle, a More Subtle Violation.

However, there are other, far more subtle, ways of violating the LSP. Consider an application which uses the `Rectangle` class as described below:

``````class Rectangle
{
public:
void SetWidth(double w) {itsWidth=w;}
void SetHeight(double h) {itsHeight=w;}
double GetHeight() const {return itsHeight;}
double GetWidth() const {return itsWidth;}
private:
double itsWidth;
double itsHeight;
};
``````

[...] Imagine that one day the users demand the ability to manipulate squares in addition to rectangles. [...]

Clearly, a square is a rectangle for all normal intents and purposes. Since the ISA relationship holds, it is logical to model the `Square` class as being derived from `Rectangle`. [...]

`Square` will inherit the `SetWidth` and `SetHeight` functions. These functions are utterly inappropriate for a `Square`, since the width and height of a square are identical. This should be a significant clue that there is a problem with the design. However, there is a way to sidestep the problem. We could override `SetWidth` and `SetHeight` [...]

But consider the following function:

``````void f(Rectangle& r)
{
r.SetWidth(32); // calls Rectangle::SetWidth
}
``````

If we pass a reference to a `Square` object into this function, the `Square` object will be corrupted because the height won’t be changed. This is a clear violation of LSP. The function does not work for derivatives of its arguments.

[...]

#### @user2023861 2015-02-11 15:31:17

Way late, but I thought this was an interesting quote in that paper: `Now the rule for the preconditions and postconditions for derivatives, as stated by Meyer is: ...when redefining a routine [in a derivative], you may only replace its precondition by a weaker one, and its postcondition by a stronger one.` If a child-class pre-condition is stronger than a parent class pre-condition, you couldn't substitute a child for a parent without violating the pre-condition. Hence LSP.

#### @inf3rno 2017-10-09 04:00:54

@user2023861 You are perfectly right. I'll write an answer based on this.

#### @Alireza Rahmani Khalili 2017-08-16 08:40:52

In a very simple sentence, we can say:

The child class must not violate its base class characteristics. It must be capable with it. We can say it's same as subtyping.

#### @snagpaul 2016-12-18 16:54:19

I guess everyone kind of covered what LSP is technically: You basically want to be able to abstract away from subtype details and use supertypes safely.

So Liskov has 3 underlying rules:

1. Signature Rule : There should be a valid implementation of every operation of the supertype in the subtype syntactically. Something a compiler will be able to check for you. There is a little rule about throwing fewer exceptions and being at least as accessible as the supertype methods.

2. Methods Rule: The implementation of those operations is semantically sound.

• Weaker Preconditions : The subtype functions should take at least what the supertype took as input, if not more.
• Stronger Postconditions: They should produce a subset of the output the supertype methods produced.
3. Properties Rule : This goes beyond individual function calls.

• Invariants : Things that are always true must remain true. Eg. a Set's size is never negative.
• Evolutionary Properties : Usually something to do with immutability or the kind of states the object can be in. Or maybe the object only grows and never shrinks so the subtype methods shouldn't make it.

All these properties need to be preserved and the extra subtype functionality shouldn't violate supertype properties.

If these three things are taken care of , you have abstracted away from the underlying stuff and you are writing loosely coupled code.

Source: Program Development in Java - Barbara Liskov

#### @Cù Đức Hiếu 2016-08-13 14:26:50

There is a check list to determine whether or not you are violating Liskov.

• If you violate one of the following items -> you violate Liskov.
• If you dont violate any -> cant conclude anything.

Check list:

• No new exceptions should be thrown in derived class: If your base class threw ArgumentNullException then your sub classes were only allowed to throw exceptions of type ArgumentNullException or any exceptions derived from ArgumentNullException. Throwing IndexOutOfRangeException is a violation of Liskov.
• Pre-conditions cannot be strengthened: Assume your base class works with a member int. Now your sub-type requires that int to be positive. This is strengthened pre-conditions, and now any code that worked perfectly fine before with negative ints is broken.
• Post-conditions cannot be weakened: Assume your base class required all connections to database should be closed before the method returned. In your sub-class you overrode that method and leaved connection open for further reuse. You have weakened the post-conditions of that method.
• Invariants must be preserved: The most difficult and painful constraint to fulfill. Invariants are some time hidden in the base class and the only way to reveal them is to read the code of the base class. Basically you have to be sure when you override a method anything unchangeable must remain unchanged after your overridden method executed. The best thing I can think of is to enforce this invariant constraints in the base class but that would not be easy.
• History Constraint: When overriding a method you are not allowed to modify an un-modifiable property in the base class. Take a look at these code and you can see Name is defined to be un-modifiable (private set) but SubType introduces new method that allows modifying it (through reflection):

``````public class SuperType
{
public string Name { get; private set; }
public SuperType(string name, int age)
{
Name = name;
Age = age;
}
}
public class SubType : SuperType
{
public void ChangeName(string newName)
{
var propertyType = base.GetType().GetProperty("Name").SetValue(this, newName);
}
}
``````

There are 2 others items: Contravariance of method arguments and Covariance of return types. But it is not possible in C# (I'm a C# developer) so I dont care about them.

Reference:

#### @LCarter 2017-09-05 03:48:34

I'm a C# developer also and I will tell your last statement isn't true as of Visual Studio 2010, with the .Net 4.0 framework. Covariance of return types allows for a more derived return type than what was defined by the interface. Example: Example: IEnumerable<T> (T is covariant) IEnumerator<T> (T is covariant) IQueryable<T> (T is covariant) IGrouping<TKey, TElement> (TKey and TElement are covariant) IComparer<T> (T is contravariant) IEqualityComparer<T> (T is contravariant) IComparable<T> (T is contravariant) msdn.microsoft.com/en-us/library/dd233059(v=vs.100).aspx

#### @Mike 2018-06-12 13:01:16

Great and focused answer (although the original questions was about examples more than rules).

#### @Raghu Reddy Muttana 2016-08-12 17:16:29

LISKOV SUBSTITUTION PRINCIPLE (From Mark Seemann book) states that we should be able to replace one implementation of an interface with another without breaking either client or implementation.It’s this principle that enables to address requirements that occur in the future, even if we can’t foresee them today.

If we unplug the computer from the wall (Implementation), neither the wall outlet (Interface) nor the computer (Client) breaks down (in fact, if it’s a laptop computer, it can even run on its batteries for a period of time). With software, however, a client often expects a service to be available. If the service was removed, we get a NullReferenceException. To deal with this type of situation, we can create an implementation of an interface that does “nothing.” This is a design pattern known as Null Object,[4] and it corresponds roughly to unplugging the computer from the wall. Because we’re using loose coupling, we can replace a real implementation with something that does nothing without causing trouble.

#### @Prasa 2016-05-03 19:34:38

The clearest explanation for LSP I found so far has been "The Liskov Substitution Principle says that the object of a derived class should be able to replace an object of the base class without bringing any errors in the system or modifying the behavior of the base class" from here. The article gives code example for violating LSP and fixing it.

#### @sebenalern 2016-05-03 19:51:01

Please provide the examples of code on stackoverflow.

#### @Shelby Moore III 2011-11-26 16:35:21

LSP is necessary where some code thinks it is calling the methods of a type `T`, and may unknowingly call the methods of a type `S`, where `S extends T` (i.e. `S` inherits, derives from, or is a subtype of, the supertype `T`).

For example, this occurs where a function with an input parameter of type `T`, is called (i.e. invoked) with an argument value of type `S`. Or, where an identifier of type `T`, is assigned a value of type `S`.

``````val id : T = new S() // id thinks it's a T, but is a S
``````

LSP requires the expectations (i.e. invariants) for methods of type `T` (e.g. `Rectangle`), not be violated when the methods of type `S` (e.g. `Square`) are called instead.

``````val rect : Rectangle = new Square(5) // thinks it's a Rectangle, but is a Square
val rect2 : Rectangle = rect.setWidth(10) // height is 10, LSP violation
``````

Even a type with immutable fields still has invariants, e.g. the immutable Rectangle setters expect dimensions to be independently modified, but the immutable Square setters violate this expectation.

``````class Rectangle( val width : Int, val height : Int )
{
def setWidth( w : Int ) = new Rectangle(w, height)
def setHeight( h : Int ) = new Rectangle(width, h)
}

class Square( val side : Int ) extends Rectangle(side, side)
{
override def setWidth( s : Int ) = new Square(s)
override def setHeight( s : Int ) = new Square(s)
}
``````

LSP requires that each method of the subtype `S` must have contravariant input parameter(s) and a covariant output.

Contravariant means the variance is contrary to the direction of the inheritance, i.e. the type `Si`, of each input parameter of each method of the subtype `S`, must be the same or a supertype of the type `Ti` of the corresponding input parameter of the corresponding method of the supertype `T`.

Covariance means the variance is in the same direction of the inheritance, i.e. the type `So`, of the output of each method of the subtype `S`, must be the same or a subtype of the type `To` of the corresponding output of the corresponding method of the supertype `T`.

This is because if the caller thinks it has a type `T`, thinks it is calling a method of `T`, then it supplies argument(s) of type `Ti` and assigns the output to the type `To`. When it is actually calling the corresponding method of `S`, then each `Ti` input argument is assigned to a `Si` input parameter, and the `So` output is assigned to the type `To`. Thus if `Si` were not contravariant w.r.t. to `Ti`, then a subtype `Xi`—which would not be a subtype of `Si`—could be assigned to `Ti`.

Additionally, for languages (e.g. Scala or Ceylon) which have definition-site variance annotations on type polymorphism parameters (i.e. generics), the co- or contra- direction of the variance annotation for each type parameter of the type `T` must be opposite or same direction respectively to every input parameter or output (of every method of `T`) that has the type of the type parameter.

Additionally, for each input parameter or output that has a function type, the variance direction required is reversed. This rule is applied recursively.

Subtyping is appropriate where the invariants can be enumerated.

There is much ongoing research on how to model invariants, so that they are enforced by the compiler.

Typestate (see page 3) declares and enforces state invariants orthogonal to type. Alternatively, invariants can be enforced by converting assertions to types. For example, to assert that a file is open before closing it, then File.open() could return an OpenFile type, which contains a close() method that is not available in File. A tic-tac-toe API can be another example of employing typing to enforce invariants at compile-time. The type system may even be Turing-complete, e.g. Scala. Dependently-typed languages and theorem provers formalize the models of higher-order typing.

Because of the need for semantics to abstract over extension, I expect that employing typing to model invariants, i.e. unified higher-order denotational semantics, is superior to the Typestate. ‘Extension’ means the unbounded, permuted composition of uncoordinated, modular development. Because it seems to me to be the antithesis of unification and thus degrees-of-freedom, to have two mutually-dependent models (e.g. types and Typestate) for expressing the shared semantics, which can't be unified with each other for extensible composition. For example, Expression Problem-like extension was unified in the subtyping, function overloading, and parametric typing domains.

My theoretical position is that for knowledge to exist (see section “Centralization is blind and unfit”), there will never be a general model that can enforce 100% coverage of all possible invariants in a Turing-complete computer language. For knowledge to exist, unexpected possibilities much exist, i.e. disorder and entropy must always be increasing. This is the entropic force. To prove all possible computations of a potential extension, is to compute a priori all possible extension.

This is why the Halting Theorem exists, i.e. it is undecidable whether every possible program in a Turing-complete programming language terminates. It can be proven that some specific program terminates (one which all possibilities have been defined and computed). But it is impossible to prove that all possible extension of that program terminates, unless the possibilities for extension of that program is not Turing complete (e.g. via dependent-typing). Since the fundamental requirement for Turing-completeness is unbounded recursion, it is intuitive to understand how Gödel's incompleteness theorems and Russell's paradox apply to extension.

An interpretation of these theorems incorporates them in a generalized conceptual understanding of the entropic force:

• Gödel's incompleteness theorems: any formal theory, in which all arithmetic truths can be proved, is inconsistent.
• Russell's paradox: every membership rule for a set that can contain a set, either enumerates the specific type of each member or contains itself. Thus sets either cannot be extended or they are unbounded recursion. For example, the set of everything that is not a teapot, includes itself, which includes itself, which includes itself, etc…. Thus a rule is inconsistent if it (may contain a set and) does not enumerate the specific types (i.e. allows all unspecified types) and does not allow unbounded extension. This is the set of sets that are not members of themselves. This inability to be both consistent and completely enumerated over all possible extension, is Gödel's incompleteness theorems.
• Liskov Substition Principle: generally it is an undecidable problem whether any set is the subset of another, i.e. inheritance is generally undecidable.
• Linsky Referencing: it is undecidable what the computation of something is, when it is described or perceived, i.e. perception (reality) has no absolute point of reference.
• Coase's theorem: there is no external reference point, thus any barrier to unbounded external possibilities will fail.
• Second law of thermodynamics: the entire universe (a closed system, i.e. everything) trends to maximum disorder, i.e. maximum independent possibilities.

#### @aknon 2013-12-27 05:03:34

@Shelyby: You have mixed too many things. Things are not as confusing as you state them. Much of your theoretical assertions stand on flimsy grounds, like 'For knowledge to exist, unexpected possibilities much exist, .........' AND 'generally it is an undecidable problem whether any set is the subset of another, i.e. inheritance is generally undecidable' . You can start up a separate blog for each of these points. Anyways, your assertions and assumptions are highly questionable. One must not use things which one is not aware of!

#### @Shelby Moore III 2014-03-16 08:38:07

@aknon I have a blog that explains these matters in more depth. My TOE model of infinite spacetime is unbounded frequencies. It is not confusing to me that a recursive inductive function has a known start value with an infinite end bound, or a coinductive function has an unknown end value and a known start bound. Relativity is the problem once recursion is introduced. This is why Turing complete is equivalent to unbounded recursion.

#### @Soldalma 2016-12-09 14:48:19

@ShelbyMooreIII You are going in too many directions. This is not an answer.

#### @Shelby Moore III 2016-12-23 12:54:36

@Soldalma it is an answer. Don't you see it in the Answer section. Yours is a comment because it is in the comment section.

#### @Shelby Moore III 2016-12-23 13:01:03

@aknon as for your allegations of "flimsy", I've blogged and written since my reply to you in 2014.

#### @Ehsan M. Kermani 2017-06-28 18:38:39

Like your mixing with scala world!

#### @Wouter 2015-07-27 21:56:40

A square is a rectangle where the width equals the height. If the square sets two different sizes for the width and height it violates the square invariant. This is worked around by introducing side effects. But if the rectangle had a setSize(height, width) with precondition 0 < height and 0 < width. The derived subtype method requires height == width; a stronger precondition (and that violates lsp). This shows that though square is a rectangle it is not a valid subtype because the precondition is strengthened. The work around (in general a bad thing) cause a side effect and this weakens the post condition (which violates lsp). setWidth on the base has post condition 0 < width. The derived weakens it with height == width.

Therefore a resizable square is not a resizable rectangle.

#### @NotMyself 2008-09-11 15:34:26

The Liskov Substitution Principle (LSP, ) is a concept in Object Oriented Programming that states:

Functions that use pointers or references to base classes must be able to use objects of derived classes without knowing it.

At its heart LSP is about interfaces and contracts as well as how to decide when to extend a class vs. use another strategy such as composition to achieve your goal.

The most effective way I have seen to illustrate this point was in Head First OOA&D. They present a scenario where you are a developer on a project to build a framework for strategy games.

They present a class that represents a board that looks like this:

All of the methods take X and Y coordinates as parameters to locate the tile position in the two-dimensional array of `Tiles`. This will allow a game developer to manage units in the board during the course of the game.

The book goes on to change the requirements to say that the game frame work must also support 3D game boards to accommodate games that have flight. So a `ThreeDBoard` class is introduced that extends `Board`.

At first glance this seems like a good decision. `Board` provides both the `Height` and `Width` properties and `ThreeDBoard` provides the Z axis.

Where it breaks down is when you look at all the other members inherited from `Board`. The methods for `AddUnit`, `GetTile`, `GetUnits` and so on, all take both X and Y parameters in the `Board` class but the `ThreeDBoard` needs a Z parameter as well.

So you must implement those methods again with a Z parameter. The Z parameter has no context to the `Board` class and the inherited methods from the `Board` class lose their meaning. A unit of code attempting to use the `ThreeDBoard` class as its base class `Board` would be very out of luck.

Maybe we should find another approach. Instead of extending `Board`, `ThreeDBoard` should be composed of `Board` objects. One `Board` object per unit of the Z axis.

This allows us to use good object oriented principles like encapsulation and reuse and doesn’t violate LSP.

#### @Brian 2011-10-21 17:55:13

See also Circle-Ellipse Problem on Wikipedia for a similar but simpler example.

#### @Contango 2013-06-05 16:40:15

Requote from @NotMySelf: "I think the example is simply to demonstrate that inheriting from board does not make sense with in the context of ThreeDBoard and all of the method signatures are meaningless with a Z axis.".

#### @Contango 2013-06-05 16:41:18

Requote from @Chris Ammerman: "Evaluating LSP adherence can be a great tool in determining when composition is the more appropriate mechanism for extending existing functionality, rather than inheritance."

#### @Nickolay Kondratyev 2013-06-18 16:45:41

So if we add another method to a Child class but all the functionality of Parent still makes sense in the Child class would it be breaking LSP? Since on one hand we modified the interface for using the Child a bit on the other hand if we up cast the Child to be a Parent the code that expects a Parent would work fine.

#### @Gangnus 2015-10-18 08:40:51

This is an anti-Liskov example. Liskov makes us to derive Rectangle from the Square. More-parameters-class from less-parameters-class. And you have nicely shown that it is bad. It is really a good joke to have marked as an answer and to have been upvoted 200 times an anti-liskov answer for liskov question. Is Liskov principle a fallacy really?

#### @Gangnus 2015-10-18 08:42:53

@Contango And can you bring an example where inheritance is good, according to the citation in the answer here?

#### @Paulustrious 2017-08-05 14:52:03

I've seen inheritance work the wrong way. Here is an example. The base class should be 3DBoard and the derived class Board. The Board still has a Z axis of Max(Z) = Min(Z) = 1

#### @brgs 2018-07-12 13:55:15

@Nickolay Kondratyev, yep, doesn't break LSP, you solved it yourself.

#### @du369 2020-04-22 20:03:15

Can we solve the problem without using composition? I think it can be done by changing the signature of `GetUnits(int x, int y)` to `GetUnits(Position pos)` and same goes for the other functions. That way, it won't violate LSP. Correct me if I'm wrong.

#### @aknon 2013-12-27 05:20:22

I wonder why didn't anybody write about the Invariant , preconditions and post conditions of the base class that must be obeyed by the derived classes. For a derived class D to be completely sustitutable by the Base class B, class D must obey certain conditions:

• In-variants of base class must be preserved by the derived class
• Pre-conditions of the base class must not be strengthened by the derived class
• Post-conditions of the base class must not be weakened by the derived class.

So the derived must be aware of the above three conditions imposed by the base class. Hence, the rules of subtyping are pre-decided. Which means, 'IS A' relationship shall be obeyed only when certain rules are obeyed by the subtype. These rules, in the form of invariants, precoditions and postcondition, should be decided by a formal 'design contract'.

Further discussions on this available at my blog: Liskov Substitution principle

#### @Ryszard Dżegan 2013-09-09 07:32:23

I encourage you to read the article: Violating Liskov Substitution Principle (LSP).

You can find there an explanation what is the Liskov Substitution Principle, general clues helping you to guess if you have already violated it and an example of approach that will help you to make your class hierarchy be more safe.

#### @avandeursen 2013-03-25 21:26:41

An important example of the use of LSP is in software testing.

If I have a class A that is an LSP-compliant subclass of B, then I can reuse the test suite of B to test A.

To fully test subclass A, I probably need to add a few more test cases, but at the minimum I can reuse all of superclass B's test cases.

A way to realize is this by building what McGregor calls a "Parallel hierarchy for testing": My `ATest` class will inherit from `BTest`. Some form of injection is then needed to ensure the test case works with objects of type A rather than of type B (a simple template method pattern will do).

Note that reusing the super-test suite for all subclass implementations is in fact a way to test that these subclass implementations are LSP-compliant. Thus, one can also argue that one should run the superclass test suite in the context of any subclass.

See also the answer to the Stackoverflow question "Can I implement a series of reusable tests to test an interface's implementation?"

#### @Chris Ammerman 2008-09-11 16:04:55

Functions that use pointers or references to base classes must be able to use objects of derived classes without knowing it.

When I first read about LSP, I assumed that this was meant in a very strict sense, essentially equating it to interface implementation and type-safe casting. Which would mean that LSP is either ensured or not by the language itself. For example, in this strict sense, ThreeDBoard is certainly substitutable for Board, as far as the compiler is concerned.

After reading up more on the concept though I found that LSP is generally interpreted more broadly than that.

In short, what it means for client code to "know" that the object behind the pointer is of a derived type rather than the pointer type is not restricted to type-safety. Adherence to LSP is also testable through probing the objects actual behavior. That is, examining the impact of an object's state and method arguments on the results of the method calls, or the types of exceptions thrown from the object.

Going back to the example again, in theory the Board methods can be made to work just fine on ThreeDBoard. In practice however, it will be very difficult to prevent differences in behavior that client may not handle properly, without hobbling the functionality that ThreeDBoard is intended to add.

With this knowledge in hand, evaluating LSP adherence can be a great tool in determining when composition is the more appropriate mechanism for extending existing functionality, rather than inheritance.

#### @Damien Pollet 2009-04-03 00:11:54

This formulation of the LSP is way too strong:

If for each object o1 of type S there is an object o2 of type T such that for all programs P deﬁned in terms of T, the behavior of P is unchanged when o1 is substituted for o2, then S is a subtype of T.

Which basically means that S is another, completely encapsulated implementation of the exact same thing as T. And I could be bold and decide that performance is part of the behavior of P...

So, basically, any use of late-binding violates the LSP. It's the whole point of OO to to obtain a different behavior when we substitute an object of one kind for one of another kind!

The formulation cited by wikipedia is better since the property depends on the context and does not necessarily include the whole behavior of the program.

#### @DrPizza 2009-11-30 07:08:42

Erm, that formulation is Barbara Liskov's own. Barbara Liskov, “Data Abstraction and Hierarchy,” SIGPLAN Notices, 23,5 (May, 1988). It is not "way too strong", it is "exactly right", and it does not have the implication you think it has. It is strong, but has just the right amount of strength.

#### @Damien Pollet 2009-12-08 22:26:32

Then, there are very few subtypes in the real life :)

#### @SteveT 2012-10-11 19:38:45

"Behavior is unchanged" does not mean that a subtype will give you the exact same concrete result value(s). It means that the subtype's behavior matches what is expected in the base type. Example: base type Shape could have a draw() method and stipulate that this method should render the shape. Two subtypes of Shape (e.g. Square and Circle) would both implement the draw() method and the results would look different. But as long as the behavior (rendering the shape) matched the specified behavior of Shape, then Square and Circle would be subtypes of Shape in accordance with the LSP.

#### @Charlie Martin 2008-11-08 17:53:32

The LSP is a rule about the contract of the clases: if a base class satisfies a contract, then by the LSP derived classes must also satisfy that contract.

In Pseudo-python

``````class Base:
def Foo(self, arg):
# *... do stuff*

class Derived(Base):
def Foo(self, arg):
# *... do stuff*
``````

satisfies LSP if every time you call Foo on a Derived object, it gives exactly the same results as calling Foo on a Base object, as long as arg is the same.

#### @Leonid 2012-07-03 17:14:27

But ... if you always get the same behavior, then what is the point of having the derived class?

#### @Charlie Martin 2012-07-04 18:06:52

You missed a point: it's the same observed behavior. You might, for example replace something with O(n) performance with something functionally equivalent, but with O(lg n) performance. Or you might replace something that accesses data implemented with MySQL and replace it with an in-memory database.

#### @Hamish Grubijan 2012-07-06 18:09:58

@Charlie Martin, coding to an interface rather than an implementation - I dig that. This is not unique to OOP; functional languages such as Clojure promote that as well. Even in terms of Java or C#, I think that using an interface rather than using an abstract class plus class hierarchies would be natural for the examples that you provide. Python is not strongly typed and does not really have interfaces, at least not explicitly. My difficulty is that I have been doing OOP for several years without adhering to SOLID. Now that I came across it, it seems limiting and almost self-contradicting.

#### @Charlie Martin 2012-07-07 19:22:07

Well, you need to go back and check out Barbara's original paper. reports-archive.adm.cs.cmu.edu/anon/1999/CMU-CS-99-156.ps It's not really stated in terms of interfaces, and it is a logical relation that holds (or doesn't) in any programming language that has some form of inheritance.

#### @asmeurer 2013-01-20 06:19:06

@HamishGrubijan I don't know who told you that Python is not strongly typed, but they were lying to you (and if you don't believe me, fire up a Python interpreter and try `2 + "2"`). Perhaps you confuse "strongly typed" with "statically typed"?

#### @Mark Amery 2013-12-27 10:57:55

@asmeurer Hamish is not wrong. "Strongly typed" isn't a well defined term; sometimes it's used to mean "has some kind of static type-checking" (Hamish's meaning), sometimes to mean "doesn't perform type coercion" (your meaning, and as usual only with regard to the specific case of 'string-to-number type coercion' - I've never seen anyone argue that C is weakly typed because you can multiply ints by floats, or that Python is because you can concatenate `u'hello'` with `'world'`), and sometimes to mean one of many other things. en.wikipedia.org/wiki/Strong_and_weak_typing

#### @asmeurer 2013-12-27 17:13:28

Well from the point of view of Liskov, those are different, because they always work. If a language supports `2 + '2'`, it still won't support `2 + 'two'`.

#### @Charlie Martin 2013-12-27 18:11:57

Oddly, @MarkAmery, the wiki article you link supports my use of 'strongly typed'. Just because people have been using it wrongly doesn't make the definition wrong. "In 1974, Liskov and Zilles described a strong-typed language as one in which "whenever an object is passed from a calling function to a called function, its type must be compatible with the type declared in the called function."

#### @Daniel 2018-10-26 22:11:12

@CharlieMartin, if I understand your answer correctly, then LSP is the ability to replace any instance of a parent class with an instance of one of its child classes without negative side effects, correct?

### [SOLVED] What exactly is RESTful programming?

• 2009-03-22 14:45:39
• hasen
• 1655344 View
• 3981 Score
• Tags:   http rest definition