To me, the Liskov Substitution Principle (LSP) was best explained as "require no more, ensure no less."
Require no more: any valid input for the superclass must be valid input for the subclass. For example: suppose you have a class MyClass with a method totalLength(List<String> strings). If you have subclass MySubClass extends MyClass, then having the method totalLength only accept instances of ArrayList (and fail when using a LinkedList) would violate this principle. If the subclass would allow more than just lists, and accept any Collection<String>, then this would be perfectly fine according to the LSP. The compiler might complain (although it's been a while since I wrote Java so I don't know for sure), but it perfectly fits within the LSP.
Ensure no less: for the return value, it should be the other way round. If the superclass has a method List<String> getNames(), then a valid substitution in the subclass might be ArrayList<String> getNames(). Again, not sure if Java allows it, but as long as the return value is an instance of the return type defined in the superclass, the LSP would allow any promise. You're ensuring that it returns a List<String>, and it even is an ArrayList<String>!
If, on the other hand, your subclass would want to return a Collection<String>, this is not allowed under LSP. You could be returning a List<String>, but it could also be a HashSet<String>, which does not implement the List<String> interface. You would no longer ensure that it is a List.
I think Java prevents (some form of) LSP violations by requiring the signatures to be exactly the same, but there might be ways to try and circumvent them. Please don't :)
Thank you for the good explaination.
Yes, Java prevents LSP violations while overriding the method. It does not allow you to change return type, however you can return instance of subtype also known as Covariant return type.
For further actions, you may consider blocking this person and/or reporting abuse
We're a place where coders share, stay up-to-date and grow their careers.
To me, the Liskov Substitution Principle (LSP) was best explained as "require no more, ensure no less."
Require no more: any valid input for the superclass must be valid input for the subclass. For example: suppose you have a class
MyClass
with a methodtotalLength(List<String> strings)
. If you have subclassMySubClass extends MyClass
, then having the method totalLength only accept instances ofArrayList
(and fail when using aLinkedList
) would violate this principle. If the subclass would allow more than just lists, and accept anyCollection<String>
, then this would be perfectly fine according to the LSP. The compiler might complain (although it's been a while since I wrote Java so I don't know for sure), but it perfectly fits within the LSP.Ensure no less: for the return value, it should be the other way round. If the superclass has a method
List<String> getNames()
, then a valid substitution in the subclass might beArrayList<String> getNames()
. Again, not sure if Java allows it, but as long as the return value is an instance of the return type defined in the superclass, the LSP would allow any promise. You're ensuring that it returns aList<String>
, and it even is anArrayList<String>
!If, on the other hand, your subclass would want to return a
Collection<String>
, this is not allowed under LSP. You could be returning aList<String>
, but it could also be aHashSet<String>
, which does not implement theList<String>
interface. You would no longer ensure that it is aList
.I think Java prevents (some form of) LSP violations by requiring the signatures to be exactly the same, but there might be ways to try and circumvent them. Please don't :)
Thank you for the good explaination.
Yes, Java prevents LSP violations while overriding the method. It does not allow you to change return type, however you can return instance of subtype also known as Covariant return type.