32

Fairly straightforward question. In C++ the parent constructor will be implicitly called before the child constructor, so what logic is there for PHP not to do things this way?

EDIT: I've got a good answer from Lukman, but I was hoping for more of a reason why there is a difference. Maybe the question should be why does C++ not allow custom calling of parent constructors? I guess that's another question though.

Skilldrick
  • 69,215
  • 34
  • 177
  • 229
  • 2
    Yes, I understand that! I'm sure there are differences in the languages that have influenced the decision to either call or not call the parent - I want to know the reasons. – Skilldrick Dec 15 '09 at 10:28
  • 8
    That's a bit like saying "Why do dogs not quack?": "Because they are not ducks." – Skilldrick Dec 15 '09 at 10:30
  • 2Skilldrick: looks like this is the answer for the question :) – BinaryButterfly Dec 15 '09 at 11:15
  • Because it's a terrible language that should be avoided. PHP is a fractal of bad design. - eev.ee/blog/2012/04/09/php-a-fractal-of-bad-design . C++ does "kind of allow you to" by overloading the ctor with an empty one and inheriting through that signature instead. A constructor should do what it says on the tin, it should be called when the object is constructed and should construct the object, if it does not, then it is forgetting its purpose. PHP is full of quirks like this and just really don't have any good reason behind them, seriously. Need any help learning C#, just ask. – Jimmyt1988 Jul 31 '16 at 01:57

3 Answers3

28

I think it's a good thing that PHP makes you call parent's constructor manually, because it allows child's constructor such as following:

public function __construct() {
   // set up variables that parent::__construct() requires
   $var1 = get_stuff_from_db();
   $var2 = get_stuff_from_webservice();

   parent::__construct($var1, $var2);

   // continue setting up $this var
   $this->default = 'Default';
   $this->do_some_secret_stuff();
}

Or even:

public function __construct($param) {
   // call differently based on condition
   if (is_array($param))
      $param['id'] = 0;
      parent::__construct($param);
   }
   else {
      parent::__construct($param, 0, TRUE);
   }

   // continue setting up $this var
   $this->default = 'Default';
   $this->do_some_secret_stuff();
}

Meaning, you are free to call the parent constructor anywhere within the child's and you are free to do stuff before and after the call. Ain't that a feature indeed?

Lukman
  • 18,462
  • 6
  • 56
  • 66
  • 1
    Notice that you could easily have the parent constructor be automatically called only when the constructor body didn't already contain an explicit call to it. – putgeminmouth Jan 06 '11 at 07:37
  • 1
    A base class that requires a child class to do initialization before it can initialize itself... :O I would strongly recommend anyone in that scenario to reconsider their application design. Then again, there's no limit to the potential kludge factor with PHP. – brettwhiteman Jun 15 '15 at 22:05
  • It's bad because the constructor should always be called when an object is instantiated. Through the inheritance cycle, the inherited object type is instantiated and yet has a flag stating the constructor should not be fired. This breaks the general constructor rule and leads to confusion (proof is in the OP). On the other hand, languages such as C# or C++ allow delayed execution of constructors by implicitly asking for it, rather than breaking the default rule of constructors being called on instantiation. This is a really stupid part of PHP and should be resolved. – Jimmyt1988 Jul 28 '16 at 17:24
  • 1
    @developerbmw - Think again. Why would you create a function to "Instantiate required objects" if you are supplied with a constructor for that very task. In fact even the PHP documentation states: "it is suitable for any initialization that the object may need before it is used.". Please do not make any recommendations to others as you may be misguiding them. This is a fundamental oversight of PHP and it's confusing for newcomers to the language. It should be resolved and set as a configuration for PHP so that legacy code is not broken. – Jimmyt1988 Jul 28 '16 at 17:30
  • @Jimmyt1988 I'm not saying don't use constructors. I was recommending not to have, and I quote, "a base class that requires a child class to do initialization before it can initialize itself". Please read and understand comments in their entirety before commenting yourself. – brettwhiteman Jul 30 '16 at 00:01
  • @developerbmw i knew exactly what you meant you tart. Lol. And i answered as i intended. Things that look the same, should act the same... not just randomly change. And having inherited classes constructors filled with initialization parts, is not only fine, it makes literal sense in many cases, so we should not need to listen to "reconsider their application design". A child cannot exist without his parent being born first, so let daddy and mummy create themselves to give birth to the child. Real life scenario. It's just logic. – Jimmyt1988 Jul 31 '16 at 01:29
  • @Lukman, it's a confusing "feature" that breaks the law of constructors defined in PHP. Things that look the same should act the same. As a PHP developer for over 8 years, I have come to understand that PHP is full of absolute hellish issues that come from stupid choices made from day 1. Whoever sat down and thought this was a good idea, is most likely tucked up in a jail sell for selling "sweets" to little children. "feature", bleurgh. – Jimmyt1988 Jul 31 '16 at 01:38
  • @Jimmyt1988 you've misinterpreted what I said again. "a base class that **requires a child class to do initialization before it** can initialize itself". You're referring to the opposite scenario, the parent initializing before the child. I'm talking about **children running initialization logic before their parents** (i.e. putting `parent::__construct();` at the end of the constructor) which, as I hope you understand, makes no sense. – brettwhiteman Aug 01 '16 at 06:38
  • @developerbmw - You are a sexy beaver, you're right. we're in complete agreement. How can i repay you? . lmao. PHP is so grotesque, it's almost as bad as me mis-understanding your comment. – Jimmyt1988 Aug 01 '16 at 10:41
  • 2
    @developerbmw: Perhaps you are forgetting that there are two types of Inheritance; Generalization and Specialization. When you extend a Parent Class using Child Class, this is Specialization which does not make the child class constructor to call parent class constructor explicitly. However, when you implement Generalization (factoring out common functionality in base class) then the same can be a valid use-case. Second, in ORMs entity-object is hydrated without calling constructor. I see wisdom in the flexibility that PHP provides to its programmers. – Fakhar Anwar Dec 30 '17 at 18:21
12

When you don't have a constructor in the child class, then the parent one is automatically called.

If you decided to add a constructor to the child class, then of course you need to explicitly call the parent constructor. If you are already taking the time to add a constructor to your child class, then adding one more line of code parent::__construct(); doesn't seem to be a big deal. But the overriding is actually a convenient flexibility.

prograhammer
  • 20,132
  • 13
  • 91
  • 118
  • 3
    PHP is the only language that bad design can be called "A convenient flexibility" :D – brettwhiteman Jun 15 '15 at 22:07
  • 1
    Not sure what you are saying here? I think it's actual better design to have only one constructor responsible for getting the object into a valid state. By mixing between child and parent constructor I would say there is more to keep track of. Or otherwise, just don't create a child constructor. So PHP is conveniently encouraging the use of a single constructor. – prograhammer Jun 16 '15 at 15:24
  • 1
    @Brett what kind of bad design are you talking about; care to explain? – Kyslik Sep 03 '15 at 11:15
  • @Kyslik having to call the parent constructor explicitly could lead to problems if it is forgotten. You could argue that it may be helpful to be able to omit calling the parent constructor but in this case you should reconsider your class design. – brettwhiteman Sep 04 '15 at 04:46
  • In this case you can make some kind of "throw new exception: hey constructor wasn't called" (or something simmilar in parent class) and problem is solved... I want to be my code DRY therefore I use abstract parent and work with children only if it makes any sense. – Kyslik Sep 07 '15 at 08:30
1

to avoid tight coupling that's why inheritance (extend keyword in java) is evil and interface class is prefered see Javaworld article: http://www.javaworld.com/javaworld/jw-08-2003/jw-0801-toolbox.html

Still it would be great if there was some instruction to call the parent at some point with a special keyword like forward but I have not yet seen this in any language (even Rebol) except in an unknown language invented by Paul Allen (yeah the co-founder of Microsoft) which is Openscript.

Rebol Tutorial
  • 2,738
  • 2
  • 25
  • 36
  • calling parent's method? lots of OOP languages have that. Like `parent` prefix in PHP, `super()` in Python, `super` in Java and even using the parent class name like `BaseClass::method()` in C++. – Lukman Dec 21 '09 at 16:01
  • ALL OOP have that that's part of OOP :). That doesn't mean you should overuse it. – Rebol Tutorial Dec 25 '09 at 19:49
  • Inheritance is evil? What? So you're saying that the very fact a snake and a giraffe are animals, you should not inherit any attributes of an animal class, but rather... what? create an interface that has a method that denotes pointers to an animal? What? How is that even correct? Sheesh. And don't get me onto people saying "multiple inheritance shouldn't exist", there are real life cases where it makes logical sense. They are rare cases, but they do exist. – Jimmyt1988 Jul 31 '16 at 01:34
  • @Jimmyt1988 For the particular case of animals, it's perfectly valid to use inheritance. However, when coding real world applications, it is not common to have that kind of domain objects. In those scenarios, devs often say "I will extend this class so I dont need to re implement this logic". That's exploiting inheritance in a way it's not meant to be used – Fermin Silva Oct 18 '16 at 15:45
  • @Fermin Silva - so you're saying when you make a game about animals, or alien species, or ships, or any other off of this world object, you don't find it useful or even... meaningful? What about materials, like Titanium and Alloy, you don't want to inherit from metal? or Apparel like Trousers and skirt doesn't want to inherit from Clothes? This is what it's for buddy, and it occurs in almost every program / game i write. See the difference, A car does not inherit from engine, it doesn't make sense. It contains an engine, that's when you have pointers. – Jimmyt1988 Oct 19 '16 at 08:27
  • @Jimmyt1988 for animals I said "it's perfectly valid to use inheritance", so it's useful and meaningful. The same for the materials example. However, for real world business applications (specially in PHP), that kind of objects are rarely found, and you work mostly with controllers, daos, users, items, etc. where inheritance is not so obvious – Fermin Silva Oct 19 '16 at 16:27
  • "real world business applications (specially in PHP), that kind of objects are rarely found". I disagree. What about, Video, PDF, Image all inherit from Media. What about Project One, Project Two, inherit from Project. What about... Controller One, Controller Two inherit from BaseController. They are common. Fact. – Jimmyt1988 Oct 20 '16 at 10:14