Constructors signature and LSP

“Objects in a program should be replaceable with instances of their subtypes without altering the correctness of that program.” – Barbara Liskov

From time to time we all encounter oddity of the language that we use and the feeling of strangeness of course is simply caused by some gaps in our knowledge. When I was building some CLI commands for my Magento’s module I found that I must extend Symfony’s Command class. Nihil novi sub sole, however I also wanted to inject my custom ThemeInstaller class to delegate some responsibilities. Then I realized that I will not be able to do that…

…because the parent class already had a constructor with the following signature:

Great, “I need to preserve this signature, that’s obvious” – I thought. But how did they manage to inject anything into inheriting class? Ok, let’s find out…

Looking for any command class… and… it hit me! What is this?

How is that possible that they have changed signature of a method without getting an exception? Did I miss something? At that moment I was sure that PHP will throw an exception if I try to change the constructor’s signature but it is not the behavior I observe in this case. Something was happening and I was not sure what. The best solution is to dig up for relevant information and that obviously led me to PHP’s documentation.

Unlike with other methods, PHP will not generate an E_STRICT level error message when __construct() is overridden with different parameters than the parent __construct() method has.

Ok, It’s a feature not a bug, but how come that we can ignore signatures of constructors? How can I prevent child class from changing the signature? Should I even do that? I  was confused.

After some research I found that the observable situation is a consequence of the Liskov Substitution Principle, a well known L from the SOLID. I was actually aware of this rule which says that a subtypes must be substitutable for their base types. I knew that from C. Martin’s book “Agile Principles, Patterns, and Practices” but obviously I misunderstood some fundamentals there. The need for understanding pushed me further. Let’s think about the substitution and consider the following classes:

Are those classes violate LSP? If we would like to substitute Animal class with a Tiger then obviously we will violate the LSP because of the inconsistency between walk methods. We can’t expect that in any possible contexts It will be possible to interchange them. If a client is using Tiger::walk() method then switching class to Animal is not possible. We messed with the consistency of method’s signature ant that lead us into troubles. Also, in case of PHP we will get an error.

In other words, subclass should not break the functionality if replacing parent class. If client can use Animal it should be able to use the Tiger as well.

What about constructors then? Does changing the signature break client’s functionality or not? Command class has a behaviour described in terms of its methods. Constructor gives a life to an object and set its initial state. It does not affect the functionality. Then if we change the constructor’s signature it will not affect the behaviour of the class in terms of functionality and public interface so any client is able to use the child class without breaking the application.

Actually, this reasoning is true only if the behaviour of constructor is restricted to setting up the object not to perform that lead to observable behaviour.

I described my own approach to this problem but of course there are some classic examples. Most widely known is the one with squares and rectangles.  You can find it on OODesign however i strongly recommend to check the Uncle’s Bob literature, his articles or maybe his screen casts about SOLID in general if you do not feel like reading a book is a good idea.

I hope that I lighted up the candle of curiosity for you.

And as always, see you soon!