Search code examples
pythonoopdesign-patternssolid-principlesliskov-substitution-principle

Violation of the LSP-principle using extra constructor parameters in subtypes


I've been reading about the Liskov Substitution Principle when I noticed this answer. It has a Circle and a ColoredCircle type where the constructor of ColoredCircle takes one extra argument; the color.

class Circle:
    radius: int

    def __init__(self, radius: int) -> None:
        self.radius = radius

class ColoredCircle(Circle):
    radius: int
    color: str

    def __init__(self, radius: int, color: str) -> None:
        super().__init__(radius)
        self.color = color

Doesn't this violate one of the requirements below? (taken from this answer). The only other option in the case of the ColoredCircle would be a public variable or a set_color method.

Pre-conditions cannot be strengthened: Assume your base class works with a member int. Now your sub-type requires that int to be positive. This is strengthened pre-conditions, and now any code that worked perfectly fine before with negative ints is broken.

If I'm searching in the wrong direction here, please let me know. Also, what if a subtype has many more parameters to handle, how would one normally manage those, is a new abstraction always nessacery?


Solution

  • When a class X has a constructor, the constructor is not a method on objects of type X. Since it is not a method on objects of type X, it doesn't have to exist as a method on objects of derived types, either -- it's irrelevant to LSP.