4

I'm trying to follow LSP in practical programming. And I wonder if different constructors of subclasses violate it. It would be great to hear an explanation instead of just yes/no. Thanks much!

P.S. If the answer is no, how do I make different strategies with different input without violating LSP?

class IStrategy
{
    public:
        virtual void use() = 0;
};

class FooStrategy : public IStrategy
{
    public:
        FooStrategy(A a, B b) { c = /* some operations with a, b */ }
        virtual void use() { std::cout << c; }
    private:
        C c;
};

class BarStrategy : public IStrategy
{
    public:
        BarStrategy(D d, E e) { f = /* some operations with d, e */ }
        virtual void use() { std::cout << f; }
    private:
        F f;
};
1

2 Answers 2

13

Generally constructors are not considered to be part of the Liskov substitution Principle (LSP). The LSP with objects, not classes:

What is wanted here is something like the following substitution property: If for each object o1 of type S there is an object o2 of type T such that for all programs P defined in terms of T, the behavior of P is unchanged when o1 is substituted for o2 then S is a subtype of T. (quoted this PDF file)

Since an object doesn't exist until after construction, the constructor itself is generally consider to be out of scope. The LSP wants all subclasses to behave the same. How they get to that behaviour is a different matter.

This means you're code example is not in violation of the LSP per se. The constructor and the private methods are not part of the public contract when viewed from a LSP perspective.

Do keep in mind that LSP goes a lot further than function signatures. If a parent throws an exception in a specific case, so should the children. If a parent doesn't children can't start throwing execptions all of a sudden, if a getStock function in a parent returns an integer, a child can't start returning stock objects, etc, etc

The LSP deals with every aspect of public behaviour an object has.

A common solution to creating strategies with different constructors is the factory pattern by the way.

4
  • So my example seems not violating the LSP, right?
    – Kolyunya
    Dec 10, 2012 at 8:01
  • As far as the example goes, it is not in violation of the LSP, I've updated my answer to reflect that.
    – hoppa
    Dec 10, 2012 at 8:15
  • Did the author of that quote make a typo when she said, "...then S is a subtype...", meaning, "...*when* S is a subtype..."? I'm trying to analyze that quote, but that phrase is getting in the way. (Apparently italics isn't working the same way in the comments.) Jun 13, 2014 at 13:08
  • While constructors are precluded from the type specification, they are included in the invariant definitions. sec 4.3 of Behavioral Subtyping Using Invariants and Constraints
    – dietbuddha
    Aug 2, 2015 at 22:13
5

TL;DR: Different subtype constructors are not only ok, they are expected.

Liskov directly addresses the usage of different constructors in her paper Behavioral Subtyping Using Invariants and Constraints which is the formalization of the principle.

"..omitting creators [from the type specification] makes it easy for a type to have multiple implementations, allows new creators to be added later, and reflects common usage"

This then shows that alternative constructors in the subtype are not only okay, but expected. It is also further addressed explicitly in the summary of the paper.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.