SOLID Design Principles – Part 3

SOLID Design principles

Last week we looked at the second of the SOLID design principles – the Open-Closed principle – in more detail. This week we’ll cover the next one in the acronym: the Liskov Substitution principle (LSP).

If you missed the previous posts in this sequence, you can find them here:

The Liskov Substitution Principle (LSP)

“Derived classes must be usable through the base class interface without the user knowing the difference”.

Wherever a superclass is needed, an instance of a derived class should be able to be substituted. That requires that subclasses must behave in the same way as the superclass. To achieve that, our subclasses need to follow these rules:

  • Don’t have any stricter validation rules on input parameters than the superclass has.
  • Apply at least the same rules to all output parameters as applied by the superclass.

The Liskov Substitution principle is described in detail in: Barbara Liskov and Jeanette Wing, “A Behavioral Notion of Subtyping”, ACM Transactions on Programming Languages and Systems, Volume 16, No 6, November 1994, pages 1811-1841. You can read the whole paper.

Quoting from the abstract of the paper: “The use of hierarchy is an important component in object-oriented design. Hierarchy allows the use of type families, in which higher-level super-types capture the behaviour that all of their subtypes have in common. …The relationship should ensure that any property proved about super-type objects also holds for subtype objects…”

Simply put, the subclass objects should behave in the same way as superclass objects as far as anyone using the superclass objects can tell. We should be able to substitute an object of any subclass in a program that expects a superclass object, and the program should still behave reasonably. It extends the Open-Closed Principle by focusing on the behaviour of a superclass and its subclasses.

EventLogger Example

In last week’s tip on the Open-Closed Principle, we created a NotifyingEventLogger class that extended our EventLogger class to send an email or SMS notification when logging an event.

Let’s see the Liskov Substitution principle in action. When we require an EventLogger object, we can either create an instance of the EventLogger class or an instance of the NotifyingEventLogger class, e.g:

EventLogger logger = new EventLogger();
// OR
EventLogger logger = new NotifyingEventLogger();

// the application behaves as expected 
// whichever instance was created
logger.log("A message to be logged");

Collections Example

We use the Liskov Substitution principle all the time when using the Java Collections API. Let’s say that we need a collection of Employee objects. We could choose the trusted ArrayList class by using the following code:

ArrayList list = new ArrayList<>();

An ArrayList works well when it’s a fixed size, but slows down when we need to add (or delete) elements. If we need a collection that’s faster when adding elements, we could choose a LinkedList as follows:

LinkedList list = new LinkedList<>();

The problem here is that we have to change the type of the collection variable and recompile the code. A better approach would be to use the List interface which both classes implement:

List list;
list = new ArrayList<>();
// OR
list = new LinkedList<>(); 

We could then pass the concrete class type through at runtime by using the Class.forName() method.

The best approach would be to use the top-level Collection interface as the compile time type of the collection variable, as follows:

Collection collection;

This would allow us to instantiate an object of *any* concrete class implementing the Collection interface:

collection = new ArrayList<>();
// OR
collection = new LinkedList<>();
// OR
collection = new TreeSet<>();
// OR
collection = new HashSet<>();
// etc.

This is the beauty of the Liskov Substitution principle!

What’s next?

In next week’s tip, we’ll look at the next principle in the acronym: the Interface Segregation principle (LSP).

As always, please share your comments and questions. If you missed the previous articles, you can find them here:

Leave a Comment

Your email address will not be published. Required fields are marked *

Code like a Java Guru!

Thank You

We're Excited!

Thank you for completing the form. We're excited that you have chosen to contact us about training. We will process the information as soon as we can, and we will do our best to contact you within 1 working day. (Please note that our offices are closed over weekends and public holidays.)

Don't Worry

Our privacy policy ensures your data is safe: Incus Data does not sell or otherwise distribute email addresses. We will not divulge your personal information to anyone unless specifically authorised by you.

If you need any further information, please contact us on tel: (27) 12-666-2020 or email info@incusdata.com

How can we help you?

Let us contact you about your training requirements. Just fill in a few details, and we’ll get right back to you.

Your Java tip is on its way!

Check that incusdata.com is an approved sender, so that your Java tips don’t land up in the spam folder.

Our privacy policy means your data is safe. You can unsubscribe from these tips at any time.