Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does PHP allow "incompatible" constructors?

Here's a couple of snippets:

  1. Overriding constructor method has an extra parameter.

    class Cat {     function __construct() {} }  class Lion extends Cat {     function __construct($param) {} } 
  2. Overriding (regular) method has an extra parameter.

    class Cat {     function doSomething() {} }  class Lion extends Cat {     function doSomething($param) {} } 

The first would work, while the second would throw Declaration of Lion::doSomething() should be compatible with that of Cat::doSomething().

Why the special attitude towards constructor methods?

like image 949
Emanuil Rusev Avatar asked Mar 14 '13 15:03

Emanuil Rusev


People also ask

Does PHP allow multiple constructors?

Note: PHP lacks support for declaring multiple constructors of different numbers of parameters for a class unlike languages such as Java. Multiple Constructors: More than one constructor in a single class for initializing instances are available.

Does PHP support constructor?

PHP allows developers to declare constructor methods for classes. Classes which have a constructor method call this method on each newly-created object, so it is suitable for any initialization that the object may need before it is used.

Why do we need constructors in PHP?

A constructor allows you to initialize an object's properties upon creation of the object. If you create a __construct() function, PHP will automatically call this function when you create an object from a class.

Can we override constructor in PHP?

Explanation. In PHP, the only rule to overriding constructors is that there are no rules! Constructors can be overridden with any signature. Their parameters can be changed freely and without consequence.


1 Answers

To understand why they are treated differently, you have to understand Liskov's Substitution Principle, which states

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." - BarbaraLiskov, Data Abstraction and Hierarchy, SIGPLAN Notices, 23,5 (May, 1988).

In a nutshell this means any class using your Lion or Cat should be able to reliably call doSomething on it, regardless of the class being one or the other. If you change the method signature, this is no longer guaranteed (you may widen it, but not narrow it though).

Very simple Example

public function doSomethingWithFeline(Cat $feline) {     $feline->doSomething(42); } 

Since Lion extends Cat, you established an is-a relationship, meaning doSomethingWithFeline will accept a Lion for a Cat. Now imagine you add a required argument to doSomething in Lion. The code above would break because it is not passing that new param. Hence, the need for compatible signatures.

LSP does not apply to constructors though, because subtypes might have different dependencies. For instance if you have a FileLogger and a DBLogger, the ctors (constructors) of the first would require a filename, while the latter would require a db adapter. As such, ctors are about concrete implementations and not part of the contract between classes.

like image 120
Gordon Avatar answered Oct 11 '22 02:10

Gordon