By random512

2013-12-31 17:33:13 8 Comments

The Liskov Substitution Principle states that a subtype should be substitutable for that type (without altering the correctness of the program).

  • Can someone please provide an example of this principle in the domain of vehicles (automotives)?
  • Can someone please provide an example of a violation of this principle in the domain of vehicles?

I've read about the square/rectangle example, but I think that an example with vehicles will give me a better understanding of the concept.


@brighty 2015-02-10 15:07:51

In my opinion, to archieve the LSP, subtypes can never add new public methods. Just private methods and fields. And of course subtypes can override methods of the baseclass. If a subtype has a single public method which the basetype doesn't have, you simply cannot substitute the subtype with the basetype. If you pass an instance to a client's method whereby you receive a subtype's instance but the parameter's type is the basetype or if you have a collection of type basetype where also subytpes are part of, then how can you ever call the method of the subtype class without asking for it's type using an if statment and if the type matches, do a cast to that subtype in order to call the method on it.

@begin 2018-05-09 11:25:52

can you please recheck your ans

@brighty 2018-05-10 13:22:34

Have a look at StuartLC's posting dated Dec 31 '13 at 17:40 and you'll notice the same opinion as i have. Stuart mentioned that a downcast of the interface to access extra functionality just available in the subclass should be avoided. Why? Because it violates the LSP.

@ComDubh 2020-01-09 00:58:19

LSP refers to classes, not types, and adding a new public method to a subclass is completely fine.

@StuartLC 2013-12-31 17:40:57

For me, this 1996 Quote from Uncle Bob (Robert C Martin) summarises the LSP best:

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

In recent times, as an alternative to inheritance abstractions based on sub-classing from a (usually abstract) base/super class, we also often use interfaces for polymorphic abstraction. The LSP has implications to both the consumer, and implementation of the abstraction:

  • Any code consuming a class or interface abstraction must assume nothing else about the class beyond the defined abstraction;
  • Any subclassing of a superclass or implementation of an abstraction must adhere to the requirements and conventions of the interface to the abstraction.

LSP Compliance

Here is an example using an interface IVehicle which can have multiple implementations (alternatively, you can substitute the interface for an abstract base class with several subclasses - same effect).

interface IVehicle
   void Drive(int miles);
   void FillUpWithFuel();
   int FuelRemaining {get; } // C# syntax for a readable property

This implementation of a consumer of IVehicle stays within the bounds of LSP:

void MethodWhichUsesIVehicle(IVehicle aVehicle)
   // Knows only about the interface. Any IVehicle is supported

Glaring Violation - Runtime type switching

Here's an example of a violation of LSP, using RTTI and then Downcasting - Uncle Bob calls this a 'glaring violation':

void MethodWhichViolatesLSP(IVehicle aVehicle)
   if (aVehicle is Car)
      var car = aVehicle as Car;
      // Do something special for car - this method is not on the IVehicle interface
    // etc.

The violating method goes beyond the contracted IVehicle interface and hacks a specific path for a known implementation of the interface (or a subclass, if using inheritance instead of interfaces). Uncle Bob also explains that LSP violations using type-switching behaviour usually also violate the Open and Closed principle as well, since continual modification to the function will be required in order to accomodate new subclasses.

Violation - Pre condition is strengthened by a subtype

Another violation example would be where a "pre condition is strengthened by a subtype":

public abstract class Vehicle
    public virtual void Drive(int miles)
        Assert(miles > 0 && miles < 300); // Consumers see this as the contract

 public class Scooter : Vehicle
     public override void Drive(int miles)
         Assert(miles > 0 && miles < 50); // ** Violation

Here, the Scooter subclass attempts to Violate the LSP as it tries to strengthen (further constrain) the precondition on the base class Drive method that miles < 300, to now a maximum of less than 50 miles. This is invalid, since by the contract definition of Vehicle allows 300 miles.

Similarly, Post Conditions may not be weakened (i.e. relaxed) by a subtype.

(Users of Code Contracts in C# will note that preconditions and postconditions MUST be placed on the interface via a ContractClassFor class, and cannot be placed within implementation classes, thus avoiding the violation)

Subtle Violation - Abuse of an interface implementation by a subclass

A more subtle violation (also Uncle Bob's terminology) can be shown with a dubious derived class which implements the interface:

class ToyCar : IVehicle
    public void Drive(int miles) { /* Show flashy lights, make random sounds */ }
    public void FillUpWithFuel() {/* Again, more silly lights and noises*/}
    public int FuelRemaining {get {return 0;}}

Here, irrespective of how far the ToyCar is driven, the fuel remaining will always be zero, which will be surprising to users of the IVehicle interface (i.e. infinite MPG consumption - perpetual motion?). In this case, the problem is that despite ToyCar having implemented all of the requirements of the interface, ToyCar just inherently isn't a real IVehicle and just "rubber stamps" the interface.

One way to to prevent your interfaces or abstract base classes from being abused in this way is to ensure a good set of Unit Tests are made available on the interface / abstract base class to test that all implementations meet the expectations (and any assumptions). Unit tests are also great at documenting typical usage. e.g. this NUnit Theory will reject ToyCar from making it into your production code base:

void EnsureThatIVehicleConsumesFuelWhenDriven(IVehicle vehicle)
    Assert.IsTrue(vehicle.FuelRemaining > 0);
    int fuelBeforeDrive = vehicle.FuelRemaining;
    vehicle.Drive(20); // Fuel consumption is expected.
    Assert.IsTrue(vehicle.FuelRemaining < fuelBeforeDrive);

Edit, Re: OpenDoor

Opening doors sounds like a different concern entirely, so needs to be separated accordingly (i.e. the "S" and "I" in SOLID), e.g.

  • on a new interface IVehicleWithDoors, which could inherit IVehicle
  • or IMO better still, on a separate interface IDoor, and then vehicles like Car and Truck would implement both IVehicle and IDoor interfaces, but Scooter and Motorcycle would not.
  • or even 3 interfaces, IVehicle (Drive()), IDoor (Open()) and IVehicleWithDoors which inherits both of these.

In all cases, to avoid violating LSP, code which required objects of these interfaces should not downcast the interface to access extra functionality. The code should select the appropriate minimum interface / (super)class it needs, and stick to just the contracted functionality on that interface.

@random512 2013-12-31 18:35:13

Thanks Stuart. Given the IVehicle interface, you might have a Car, a Truck and a Motorcycle that each implements this interface. Car and Truck should have an OpenDoor method, whereas Motorcycle should not have an OpenDoor method. How would you handle this scenario to conform to LSP?

@George Geschwend 2017-06-09 23:21:09

@random512 Maybe create a function with the same arguments and return type...and have it do nothing.Check this answer:

@StuartLC 2017-06-11 05:08:27

@GeorgeGeschwend - I updated the answer a while back to include the OP's second question re OpenDoors. But rubber stamping methods is a clear indication of abuse of the design - we're trying to make something "fit into" or "conform to" an interface which just isn't applicable in this case. @anotherdave gives another good example of rubberstamping.

@George Geschwend 2017-06-13 20:58:33

@StuartLC Sorry, I was a little green regarding Liskov principal. After watching a really good video of Bob Martin discussing SOLID, got the feeling that this principal if used as a "test". Like a Vehical base class that has an openDoor() function (behavior), and you try to let Motorcycle, which has no door, inherit it ... well, it violates the Liskov Substitution principal. Even though in the real world it is acceptable to think that a motorcycle is a vehicle, in Object Oriented Modeling this may not be the case. So what to do? Don't allow Motorcycle to inherit from Vehicle.

@gimlichael 2018-03-15 09:08:04

@random512 since OpenDoor(which) requires a door, it should be a special implementation on the concrete implementation. For instance, IVehicleWithDoors (which inherits from IVehicle) could have this method, whereas IVehicle should not. Only shared components between all vehicles should be on IVehicles.

@anotherdave 2014-01-09 09:38:45

Image I want to rent a car when I'm moving house. I ring up the hire company and ask them what models they have. They tell me though that I'll just be given the next car that comes available:

public class CarHireService {
    public Car hireCar() {
        return availableCarPool.getNextCar();

But they have given me a brochure that tells me all of their models come with these features:

public interface Car {
    public void drive();
    public void playRadio();
    public void addLuggage();

That sounds just what I'm looking for, so I book a car & go away happy. On moving day, a Formula One car shows up outside my house:

public class FormulaOneCar implements Car {
    public void drive() {
        //Code to make it go super fast

    public void addLuggage() {
        throw new NotSupportedException("No room to carry luggage, sorry."); 

    public void playRadio() {
        throw new NotSupportedException("Too heavy, none included."); 

I'm not happy, because I was essentially lied to by their brochure β€” it doesn't matter if the Formula One car has a fake boot that looks like it can hold luggage but won't open, that's useless for moving house!

If I'm told that "these are the things all of our cars do", then any car I'm given should behave in this way. If I can't trust the details in their brochure, it's useless. That's the essence of the Liskov Substitution Principle.

@trnelson 2014-03-17 19:15:16

This is actually more of an example of Interface Segregation Principle, no?

@anotherdave 2014-03-18 09:20:30

Well the Interface Segregation Principle would solve the issue from another angle (as the interface then wouldn't be making promises that the concrete class can't keep)

@karlihnos 2017-07-13 10:07:05

Well, analyzing the example I can conclude: You have to implement the methods in the contract (interface), i.e. an exception is not allowed.

@anotherdave 2017-07-13 14:53:39

@karlihnos I think it's at a higher level than whether you not you throw an exception β€” as a client, you should be able to depend on a child class as an instance of its parent. A child should offer more functionality, or a different implementation, but shouldn't remove things that we know to be true about the parent class. That said, NotSupportedException and similar exceptions are definitely a smell of breaking LSP.

@begin 2018-01-24 10:41:38

I dont feel its LSP because as per Uncle Bob . bold "Functions that use pointers or references to base classes must be able to use objects of derived classes without knowing it.” We are not using this concept (in this example) anywhere

@anotherdave 2018-01-24 16:21:32

@spandey15 sure, you have to read between the lines I guess then :) the point I was making is that a function that had a reference to Car wouldn't be as to use instances of its derived class, FormulaOneCar without knowing itβ€” therefore violating LSP

@John Deters 2014-01-03 04:35:58

The Liskov Substitution Principle states that an object with a certain interface can be replaced by a different object that implements that same interface while retaining all the correctness of the original program. That means that not only does the interface have to have exactly the same types, but the behavior has to remain correct as well.

In a vehicle, you should be able to replace a part with a different part, and the car would keep working. Let's say your old radio doesn't have a digital tuner, but you want to listen to HD radio so you buy a new radio that has an HD receiver. You should be able to take the old radio out and plug in the new radio, as long as it has the same interface. On the surface, that means the electrical plug that connects the radio to the car needs to be the same shape on the new radio as it is on the old radio. If the car's plug is rectangular and has 15 pins, then the new radio's jack needs to be rectangular and have 15 pins as well.

But there are other considerations besides the mechanical fit: the electrical behavior on the plug has to be the same, too. If pin 1 on the connector for the old radio is +12V, then pin 1 on the connector for the new radio also has to be +12V. If pin 1 on the new radio was the "left speaker out" pin, the radio might short out, or blow a fuse. That would be a clear violation of the LSP.

You could also consider a situation of a downgrade: let's say your expensive radio dies, and you can only afford an AM radio. It doesn't have stereo out, but it has the same connector as your existing radio. Let's say the spec has pin 3 being left speaker out, and pin 4 being right speaker out. If your AM radio plays the monophonic signal out both pins 3 and 4, you could say that its behavior is consistent, and that would be an acceptable substitution. But if your new AM radio plays audio only on pin 3, and nothing on pin 4, the sound would be unbalanced, and that probably would not be an acceptable substitution. That situation would also violate the LSP, because while you can hear sounds, and no fuses blow, the radio doesn't meet the full specification of the interface.

@user2810910 2013-12-31 17:51:55

First, you need to define what a vehicle and automobile are. According to Google (not very complete definitions):

a thing used for transporting people or goods, esp. on land, such as a car, truck, or cart.

a road vehicle, typically with four wheels, powered by an internal combustion engine or electric
motor and able to carry a small number of people

So an automobile is a vehicle, but a vehicle is not an automobile.

Related Questions

Sponsored Content

31 Answered Questions

2 Answered Questions

1 Answered Questions

4 Answered Questions

1 Answered Questions

[SOLVED] Liskov Substitution Principle example

1 Answered Questions

Sponsored Content