Reputation: 89
LSP definition states that,If S is a subtype of T, then objects of type T in a program may be replaced with objects of type S without altering any of the desirable properties of that program.
For example, I have below classes Is this a violation of( Preconditions cannot be strengthened in a subtype). I am trying to wrap my head around this ,Can someone please provide a good example to understand it.
Class Switch:
def __init__(self,ip,dc):
self.ip=ip
self.dc=dc
class CiscoSwitch(Switch):
def __init__(self,ip,dc,zone):
super().__init__(ip,dc)
self.zone=zone
class JuniperSwitch(Switch):
def __init__(self,ip,dc,zone):
super().__init__(ip,dc)
self.zone=zone
Upvotes: 1
Views: 1274
Reputation: 867
LSP principle works through interfaces, that is, what is public in the object/value. In the case of Python, you have attributes and methods that are public and therefore, if you are implementing an interface you must adhere to it.
In your example, the Switch
class defines an interface only regarding its attributes, that is, it has the ip
and dc
fields. Since you are calling super
in CiscoSwitch
and JuniperSwitch
, they both have those fields, and therefore implement the "interface" of Switch
and they may replace it.
Now, let's tackle the conditions you mentioned:
Suppose you have an interface with a method that colors a shape and this method accepts only hexadecimal colors ("#123456"
) or rgb colors ((123,124,125)
). Suppose you create a class Rectangle that implements this interface, but it accepts only rgb colors. You're strengthening the pre-condition. If you have this line in your code:
generic_shape.color("#123456")
You cannot replace your Rectangle in it, so you are breaking LSP.
A classical example would be returning None
for a method that should not return None
. Suppose that in the Shape interface, you have a getSide
method, and you create a Circle
class, and when implementing this method, you return None
. This breaks the caller expectative and may cause an unexpected error:
side = generic_shape.get_side() # suppose it is a circle
scaled_side = side * 2 # you get an error
This one is more complex in my opinion, because it is hard to make it explicit. The only example I can think is keeping a property non-Null, suppose in your example you have a Switch that doesn't use IP (maybe uses MAC-addr), if the Switch interface expects that the ip
field should not be None, your MAC-Switch will be broking this interface.
I hope it helps!
Upvotes: 2