DEV Community

Abdullah Di'bas
Abdullah Di'bas

Posted on

Examples on the violation of Liskov Substitution Principle (LSP)

The following are some examples I've collected that demonstrate how Liskov Substitution Principle could be violated.

NOTE: Before continue if you need more details about the definition of Liskov Substitution Principle refer to its Wikipedia page Liskov substitution principle.

NOTE: The below examples don't cover all the possibilities of violating LSP.

Examples:

  1. Throwing a NotImplementedException from a derived/implementation class is a sign that the parent-child relation is not following LSP. Here in the code snippet IBird class cannot represent Duck as it has no definition for flying.
    Alt Text

  2. Hiding a virtual parent method in a child class using the new keyword also violates LSP. In the code below when the declaration type is changed from the base class EmployeeAnnualBonus to the derived class ManagerAnnualBonus the value of the annual bonus is changed, which means that they cannot be substitutable without altering the expected result.
    (Here override keyword should be used instead.)
    Alt Text

  3. Returning a value of a type that has restrictions that are unknown from the method's signature. Such as returning a value of type ReadOnlyCollection from a derived class' method while the return type in its signature is ICollection. The code below demonstrates how this approach is making unexpected behavior for the code consumer.
    Alt Text

  4. Adding an implementation for a derived method in a way that violates the system code's policy or conventions (if there is any); like when a derived method returns a null value for a list when there is a convention not to return null for empty collections but instead to return initialized collections with zero items count.

Conclusion:

It's recommended to keep code components (classes or projects) separated and to depend on abstractions instead of concrete implementations, and that makes applying Liskov Substitution principle more important. The implementation of the derived classes may not be known for the code consumer or at design time and implementing a method that returns a value or accepts parameters in a way that is unclear from its interface (or base class) will mislead who calls that code which in turns may break the code execution or result in unexpected behaviors at run time.

Top comments (0)