I'm working with SOLID principles, specifically Liskov's Substitution Principle (LSP).
I have an abstract class called Button
that defines different methods and different subclasses extend it to define some of those methods. For example I have a subclass called PauseButton
that implement only 3 methods from the abstract class.
Is that concidered a violation of LSP?
CodePudding user response:
The core idea of Liskov's Substitution Principle is that you could use instances of the subtype whenever you may use instances of the type. The subtype may be more specialized but it should comply with the same contract.
In your example, PauseButton
fulfills LSP with regard to Button
if all its "methods" (we say "operations" in UML) comply with the contract defined for Button
. It's not just about implementing the methods but making sure that the methods are compatible:
PauseButton
may not strengthen the preconditions ofButton
. I.e. if the conditions are fulfilled to perform aButton
method, you should be able to perform the corresondingPauseButton
method as well.PauseButton
may not weaken the postconditions ofButton
. I.e. ifButton
makes some promises about a method,PauseButton
must fulfill at least the same promises.- Invariants of
Button
(logical conditions that should be always true) should also be invariants ofPauseButton
.PauseButton
may have additional invariants. - History constraint: roughly speaking, it means that whereas
PauseButton
is aButton
,PauseButton
methods should not modify directly itsButton
state, without using methods of theButton
. No shortcut.
In the case of abstract subclasses, it's more delicate to verify LSP since we cannot look at direct instances. Nevertheless, the subclasses could be indirectly instantiated by concrete subclasses that provide the missing methods:
- If at least one of the three
PauseButton
methods that you implement infringes LSP (i.e. are incompatible with the same method fromButton
), thenPauseButton
violates LSP. - But if all the three methods are compliant, and if
PauseButton
does not redefine the contract of the other methods, you can assume thatPauseButton
is LSP-Compliant : you could create a concrete subclass ofPauseButton
that would be compliant, even if at the present stage such sublass doesn't exist. This fulfills the requirements for interchangeability.