Consider a rectangle and a square. If we treat them as objects it is clearly evident that a square can inherit most or all of its properties from a rectangle, since a square is a special case of a rectangle. The only restriction is that a square must have similar side lengths.
Take a look at this very basic implementation.
class Rectangle(object):
def __init__(self, x, y):
self.x = x
self.y = y
def get_area(self):
return self.x * self.y
class Square(Rectangle):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
if self.x != self.y:
raise ValueError("x and y must be equal.")
Type-checking is avoided for simplicity. I used args and kwargs inorder to make sure that the subclass(es) will be future proof. I am, however, not sure if I am doing it right. Rectangle class' __init__ might add more arguments in the future.
The question is, if x and y must be equal, why ask for both of them in the first place? Shouldn't there be only one of them? The current inheritance scheme has this restriction - the user is forced to enter x and y. How can this problem be solved. Turning x and y in to keyword arguments is not a solution, since no defaults (or None) are allowed.
Squareas a subclass ofRectangleis a classic violation of the Liskov Substitution Principle precisely because of this issue.