Is a subclass Liskov Substitutable if it disallows the same invocation of the constructor in the child as in the parent?

softwareengineering.stackexchange https://softwareengineering.stackexchange.com/questions/411048

Question

Say, I have two classes:

class FTPClient:
    def __init__(self, host, port):
        self._client = FTPDriver(host, port)
  ...

class FTPSClient(FTPClient):
    def __init__(self, host, port, username, password):
        self._client = FTPSDriver(host, port, user=username, password=password)

Objects of type FTPClient may be replaced with objects of type FTPSClient anywhere in the code. However, their __init__ methods are apparently different, so it's not possible to instantiate them in the same way. Is this a violation of LSP?

Was it helpful?

Solution

As an outside consumer, there is no way to rely on a base class' constructor when initializing a subclass. The initialization of the subclass is the subclass' responsibility and no one else's. The subclass' constructor can fall back on its ancestor's constructor (I assume this applies to all languages), but that is a free choice (it can pick any base constructor that's available), which an internal consideration made by the subclass, it is not enforced in any way (not by the compiler, the outside consumer, or any contract).

In short, there is no substitution going on during object initialization, so you logically cannot violate a substitution principle.

If you continue your line of reasoning, you run into several conflicts. If it were considered an LSP violation:

  • it would make no sense for subclasses to be able to freely define constructors as they please, since the base class would have predefined them. Every constructor for every derived child class would inherently have to be defined in the root parent class.
  • it would require the base class constructor method(s) to account for dependencies that the subclass may be using in its extension of the base class - which defeats the purpose of implementing that extension in a subclass
  • interfaces would need to specify constructor signatures. Don't forget that while interfaces slightly skirt the specific problem you're addressing here (due to methods not having a base implementation), they do still rely on polymorphism (and thus substitution principles).

The very essence of inheritance and interface implementation is that "you must provide [this contract]", not that "you must not have anything other than [this contract]".

There's a very big structural difference between requiring a minimum implementation and restricting a maximum implementation. The latter would effectively break the purpose of inheritance, would completely invalidate OCP (since you can't extend anymore) and make ISP a moot point (since a class couldn't have anything more than what its first interface demands).

OTHER TIPS

No. LSP does not consider the creation of instances because you need to know the exact class you are instantiating anyway.

LSP means that if you have an instance of a subclass, it can be used in place of an instance of the base class. Creating an instance of a subclass is not subject to LSP, since there is no complete instance yet.

Thus, LSP only means the instances must be substitutable. The classes do no have this restriction.

Licensed under: CC-BY-SA with attribution
scroll top