Object-oriented – Stack extending LinkedList. A violation of Liskov Substitution Principle

designliskov-substitutionobject-orientedobject-oriented-designsolid

A class LinkedList exists with functions such as add_first(), add_last(), add_after(), remove_first(), remove_last() and remove()

Now there is a class Stack that provides functionalities such as push(), pop(), peek() or top(), and to implement these methods it extends the LinkedList class methods. Is this a violation of Liskov Substitution Principle?

For example, consider the case add_after() to add a node at the nth position of a Linked List. This can be done in the base class but not in the Stack class. Are postconditions being weakened here or do you modify the add_after() method to add to the top of the Stack?

Also, if not a violation, is this bad design? And how would you implement the Stack functionality using the LinkedList class?

Best Answer

Now there is a class Stack that provides functionalities such as push(), pop(), peek() or top(), and to implement these methods it extends the LinkedList class methods. Is this a violation of Liskov Substitution Principle?

No. It is perfectly fine to add methods in a subtype.

For example, consider the case add_after() to add a node at the nth position of a Linked List. This can be done in the base class but not in the Stack class.

This is a violation of the LSP. The LSP says that instances of a subtype must be substitutable for instances of a supertype without changing the desirable properties of a program. If a subtype removes a method, then any code that calls that method will crash (or get a NoMethodError exception, or something along those lines). Clearly, "not crashing" is a desirable property.

Are postconditions being weakened here or do you modify the add_after() method to add to the top of the Stack?

Modifying the add_after() method in this way is a violation of the History Rule (the most important of the rules!) and thus doesn't help fixing the violation of the LSP.

And how would you implement the Stack functionality using the LinkedList class?

By using composition.

NOTE: Everything I wrote above only applies to languages which confuse subtyping and subclassing! The LSP is about subtyping, not subclassing. In a language which does not confuse the two, it would be perfectly acceptable to make Stack a subclass of LinkedList, as long as you do not make it a subtype of LinkedList.