I'm working with solid priciple, 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 that the base type, but it should comply with the same contract.
In your example, PauseButton
fulfills LSP with a 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 constraints is more complicated, but roughtly speaking, it means that since
PauseButton
is aButton
, aPauseButton
method should not modify directly the state of theButton
it is, without using methods of theButton
. No shortcut.
In the case of abstract classes, it's more delicate to verify LSP: not all the methods are defined, so we cannot look at direct instances. Nevertheless, the classes could be indirectly instantiated using concrete classes that provide the missing methods:
- If at least one of the three
PauseButton
methods that you implement infringes LSP (are incompatible with the same method fromButton
), thenPauseButton
is not compliant. - 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.