# [RFC] Default constructors

- Thread: https://externals.io/message/78935
- Original archive: https://news-web.php.net/php.internals/78935
- Started by Stanislav Malyshev on 2014-11-18T09:20:34+00:00
- Messages: 46
- Page 1 of 2: messages 1 to 25 (25 per page, add `?page=N` to the URL)
- Next page: https://externals.io/message/78935.md?page=2
- Reply by email to internals@lists.php.net
- More for agents: search with https://externals.io/search.md?q={query} · JSON API at https://externals.io/api · documentation at https://externals.io/llms.txt

---

## #78935 — Stanislav Malyshev — 2014-11-18T09:20:34+00:00

URL: https://externals.io/message/78935#78935

Hi!

I'd like to propose the following RFC, which in short would allow any
method to call parent ctor (and some other methods) even if such is not
explicitly defined:

https://wiki.php.net/rfc/default_ctor

The reasons are outlined in detail in the RFC and here:
http://php100.wordpress.com/2014/11/04/default-constructors/

The patch is not finished yet but seems to be working fine, I'll add it
to the RFC this week as soon as I finish it. I'd like to put idea out
there in the meantime and hear what everybody thinks about it.

Thanks,
Stas

---

## #78937 — Robert Stoll — 2014-11-18T10:03:26+00:00

URL: https://externals.io/message/78935#78937 · In reply to: #78935

> -----Ursprüngliche Nachricht-----
> Von: Stanislav Malyshev [mailto:smalyshev@gmail.com]
> Gesendet: Dienstag, 18. November 2014 10:21
> An: PHP Internals
> Betreff: [PHP-DEV] [RFC] Default constructors
> 
> Hi!
> 
> I'd like to propose the following RFC, which in short would allow any method to call parent ctor (and some other methods)
> even if such is not explicitly defined:
> 
> https://wiki.php.net/rfc/default_ctor
> 
> The reasons are outlined in detail in the RFC and here:
> http://php100.wordpress.com/2014/11/04/default-constructors/
> 
> The patch is not finished yet but seems to be working fine, I'll add it to the RFC this week as soon as I finish it. I'd like to put
> idea out there in the meantime and hear what everybody thinks about it.
> 
> Thanks,
> Stas
> 
> --
>  

+1
And concerning the subtle BC break, I think it is a bug that bar is currently not executed. In other cases where superfluous arguments are provided, they are evaluated. Hence, inconsistent anyway and should be fixed IMO.
Another example which outlines that the new behaviour is more appropriate:

class Foo{}
$b = 0;
//left over from refactoring, $b is currently not incremented even though it looks like that, new behaviour would fix that
$a = new Foo(++$b);

---

## #78938 — Ferenc Kovacs — 2014-11-18T12:12:38+00:00

URL: https://externals.io/message/78935#78938 · In reply to: #78935

On Tue, Nov 18, 2014 at 10:20 AM, Stanislav Malyshev <smalyshev@gmail.com>
wrote:

> Hi!
>
> I'd like to propose the following RFC, which in short would allow any
> method to call parent ctor (and some other methods) even if such is not
> explicitly defined:
>
> https://wiki.php.net/rfc/default_ctor
>
> The reasons are outlined in detail in the RFC and here:
> http://php100.wordpress.com/2014/11/04/default-constructors/
>
> The patch is not finished yet but seems to be working fine, I'll add it
> to the RFC this week as soon as I finish it. I'd like to put idea out
> there in the meantime and hear what everybody thinks about it.
>
> Thanks,
> Stas
>
> --
> 
> 
>
>

Hi Stas,
Thanks for bringing this up and working on the patch.
Last time we discussed this(
http://www.serverphorums.com/read.php?7,712222,712635), there were a couple
of people including Anthony and Sanford who were agains this feature
arguing that it would encourage bad practices so I think it would be useful
to look at those concerns if they (still) have merit.

-- 
Ferenc Kovács
@Tyr43l - http://tyrael.hu

---

## #78939 — Derick Rethans — 2014-11-18T12:23:08+00:00

URL: https://externals.io/message/78935#78939 · In reply to: #78935

> Hi!
> 
> I'd like to propose the following RFC, which in short would allow any
> method to call parent ctor (and some other methods) even if such is not
> explicitly defined:
> 
> https://wiki.php.net/rfc/default_ctor
> 
> The reasons are outlined in detail in the RFC and here:
> http://php100.wordpress.com/2014/11/04/default-constructors/
> 
> The patch is not finished yet but seems to be working fine, I'll add it
> to the RFC this week as soon as I finish it. I'd like to put idea out
> there in the meantime and hear what everybody thinks about it.

You write:

>  Also, this can lead to more subtle BC breaks. Consider this code: 

And then further on:

> No backward incompatible changes, sin...

that can not be both right.

cheers,
Derick

---

## #78940 — Ivan Enderlin @ Hoa — 2014-11-18T12:35:19+00:00

URL: https://externals.io/message/78935#78940 · In reply to: #78935

Hello :-),

Is it not simpler to create a super-object whom all objects are children 
of? Something similar to the Java `Object`?

Cheers :-).


Le 18/11/2014 10:20, Stanislav Malyshev a écrit :
> Hi!
>
> I'd like to propose the following RFC, which in short would allow any
> method to call parent ctor (and some other methods) even if such is not
> explicitly defined:
>
> https://wiki.php.net/rfc/default_ctor
>
> The reasons are outlined in detail in the RFC and here:
> http://php100.wordpress.com/2014/11/04/default-constructors/
>
> The patch is not finished yet but seems to be working fine, I'll add it
> to the RFC this week as soon as I finish it. I'd like to put idea out
> there in the meantime and hear what everybody thinks about it.
>
> Thanks,
> Stas
>

-- 
Ivan Enderlin
Developer of Hoa
http://hoa-project.net/

PhD. at DISC/Femto-ST (Vesontio) and INRIA (Cassis)
http://disc.univ-fcomte.fr/ and http://www.inria.fr/

Member of HTML and WebApps Working Group of W3C
http://w3.org/

---

## #78941 — Ferenc Kovacs — 2014-11-18T12:47:38+00:00

URL: https://externals.io/message/78935#78941 · In reply to: #78940

On Tue, Nov 18, 2014 at 1:35 PM, Ivan Enderlin @ Hoa <
ivan.enderlin@hoa-project.net> wrote:

> Hello :-),
>
> Is it not simpler to create a super-object whom all objects are children
> of? Something similar to the Java `Object`?
>
>
yeah, this was also a suggested alternative when discussing this problem
previously(see the link in my previous mail).

-- 
Ferenc Kovács
@Tyr43l - http://tyrael.hu

---

## #78942 — Andrea Faulds — 2014-11-18T13:11:17+00:00

URL: https://externals.io/message/78935#78942 · In reply to: #78941

> 
> 
> On Tue, Nov 18, 2014 at 1:35 PM, Ivan Enderlin @ Hoa <
> ivan.enderlin@hoa-project.net> wrote:
> 
> > […]
> yeah, this was also a suggested alternative when discussing this problem
> previously(see the link in my previous mail).

I'd certainly like it if everything descended from some class (Object? StdClass?), but I don't like the idea of an empty construct. As Anthony pointed out last time, you can't do inheritance and simultaneously treat the parent class as a black box.

--
Andrea Faulds
http://ajf.me/

---

## #78944 — Rowan Collins — 2014-11-18T14:19:14+00:00

URL: https://externals.io/message/78935#78944 · In reply to: #78942

Andrea Faulds wrote on 18/11/2014 13:11:
> > […]
> I'd certainly like it if everything descended from some class (Object? StdClass?), but I don't like the idea of an empty construct. As Anthony pointed out last time, you can't do inheritance and simultaneously treat the parent class as a black box.

The thing is that without any way of monkey-patching the default object, 
there isn't much difference between "all objects have a default 
constructor" and "all objects have a default parent", other than "$foo 
instanceOf Object" always returning true.

Regards,
-- 
Rowan Collins
[IMSoP]

---

## #78945 — Alexander Lisachenko — 2014-11-18T14:54:13+00:00

URL: https://externals.io/message/78935#78945 · In reply to: #78935

Hi!

2014-11-18 12:20 GMT+03:00 Stanislav Malyshev <smalyshev@gmail.com>:

>
> I'd like to propose the following RFC, which in short would allow any
> method to call parent ctor (and some other methods) even if such is not
> explicitly defined:


+1 for defining base class for all classes and addition of default
constructor implementation in it.

One more example with inconsistent ctors handling via Reflection:
http://3v4l.org/Tjn82

---

## #78949 — Stanislav Malyshev — 2014-11-18T18:54:42+00:00

URL: https://externals.io/message/78935#78949 · In reply to: #78939

Hi!

> You write:
> 
> > […]
> 
> And then further on:
> 
> > […]
> 
> that can not be both right.

Ah, but the former describes the option that has been *rejected*. The
option that was chosen instead does not have the BC break.

---

## #78950 — Stanislav Malyshev — 2014-11-18T19:00:09+00:00

URL: https://externals.io/message/78935#78950 · In reply to: #78938

Hi!

> Thanks for bringing this up and working on the patch.
> Last time we discussed
> this(http://www.serverphorums.com/read.php?7,712222,712635), there were
> a couple of people including Anthony and Sanford who were agains this
> feature arguing that it would encourage bad practices so I think it

Obviously, I disagree with that. I do not see any bad practices it
encourages - if anything, it encourages the good practice of always
calling parent ctor, practice considered so good by many that some
languages make it mandatory.

The discussion of __call etc. presented there does not seem too relevant
for me - __call was never called on missing ctor and it makes zero sense
to do so since no sane implementation uses __call do dispatch
constructors. I'll need to check though if my changes don't have BC
impact on __call (they should not, but I did not check before, so I'll
check that too).

Thanks,
Stas

---

## #78951 — Andrea Faulds — 2014-11-18T19:03:28+00:00

URL: https://externals.io/message/78935#78951 · In reply to: #78950

> 
> 
> > […]
> 
> Obviously, I disagree with that. I do not see any bad practices it
> encourages - if anything, it encourages the good practice of always
> calling parent ctor, practice considered so good by many that some
> languages make it mandatory.

Yes, calling the parent constructor is good practice. That doesn’t mean we should add this, though. Because this RFC means you can just blindly call the constructor, whether or not it exists, and expect it to work. And that is bad: If you don’t know how the parent class works, you really shouldn’t be extending it.
--
Andrea Faulds
http://ajf.me/

---

## #78952 — Stanislav Malyshev — 2014-11-18T19:05:31+00:00

URL: https://externals.io/message/78935#78952 · In reply to: #78944

Hi!

> > […]

Making everything descend from the same class may require a number of
changes and much bigger design effort than this RFC aims at, with wider
BC implications. As for not liking the idea of empty construct - that's
too bad since PHP already has it and had it since forever. You just
can't call it with parent:: syntax - but you perfectly can use it (not
sure you can say "call" since no call is actually happening) with new.

> > […]

I'm not sure what is meant here. Calling parent ctor is a base OOP
technique, everybody does that, it's one of the first best practices
people learn when doing OO. Only in PHP, it's weird since you have to
know if parent defined ctor or not, and if that changes, patch all your
descendant classes. That's just bad OO implementation.

---

## #78953 — Stanislav Malyshev — 2014-11-18T19:12:15+00:00

URL: https://externals.io/message/78935#78953 · In reply to: #78951

Hi!

> mean we should add this, though. Because this RFC means you can just
> blindly call the constructor, whether or not it exists, and expect it

Yes, that's exactly what it means and it's good, not bad - new() has
been doing that for years and nobody complained.

> to work. And that is bad: If you don’t know how the parent class
> works, you really shouldn’t be extending it. -- Andrea Faulds 

That sounds just wrong - information hiding is a basic premise of OO,
and to extend the object you shouldn't have to know the intimate details
of its implementation. In fact, in many cases you can't - such as with
internal classes. That's why we have problems with class initilization
for extending internal classes - because people are trained "you can't
just call the parent ctor, you need to verify things thoroughly first".
And that'd exactly wrong. If you know you can create an object without
parameters - new Foo() - then you should be able to extend it and call
parent::__construct() - which is supposed to do exactly the same.
Unfortunately, in PHP - unlike pretty much any other OO language - you
can not.

---

## #78954 — Alexander Kurilo — 2014-11-18T20:20:34+00:00

URL: https://externals.io/message/78935#78954 · In reply to: #78950

> Hi!
>
> > […]
>
> Obviously, I disagree with that. I do not see any bad practices it
> encourages - if anything, it encourages the good practice of always
> calling parent ctor, practice considered so good by many that some
> languages make it mandatory.

However, Java lets one have as many constructors as one wants because 
Java supports overloading and there's a default constructor that takes 
no arguments.

Does it *really* make sense for PHP? What if that parent class 'Animal' 
from your example introduces a constructor that accepts, say, both 
`$owner` and `$what` as mandatory arguments? `parent::__construct()` 
call in a descendant will appear broken (unintentionally, I suppose), 
won't it? That'll work in Java just fine, though.

---

## #78956 — Stanislav Malyshev — 2014-11-18T20:30:52+00:00

URL: https://externals.io/message/78935#78956 · In reply to: #78954

Hi!

> Does it *really* make sense for PHP? What if that parent class 'Animal'
> from your example introduces a constructor that accepts, say, both
> `$owner` and `$what` as mandatory arguments? `parent::__construct()`

Then you need to rewrite all descendant classes anyway, this would be
API change, not an API-preserving refactoring. Essentially, you take the
Animal class and replace it with entirely different class with different
requirements. You'll have to rewrite all the code that constructs Animal
objects. This obviously is not the scenario I'm talking about (and of
course nowhere near recommended practice for any maintainable code).

> call in a descendant will appear broken (unintentionally, I suppose),
> won't it? That'll work in Java just fine, though.

In Java, you can not do that - if your ctor requires 2 arguments, you'd
have to give it 2 arguments. If you still have the default ctor, that'd
be fine, and so it will be in PHP - but in PHP you can not have two ctor
functions, so in PHP you do things differently, we use optional
arguments instead of using two functions. The meaning is the same though
- if you're able to call new Foo(), you should be able to call
parent::__construct() (or super() in Java case) on Foo. Except in Java
it works and in PHP it doesn't. That's what I want to fix.

---

## #78959 — Rowan Collins — 2014-11-18T21:40:19+00:00

URL: https://externals.io/message/78935#78959 · In reply to: #78954

> Does it *really* make sense for PHP? What if that parent class 
> 'Animal' from your example introduces a constructor that accepts, say, 
> both `$owner` and `$what` as mandatory arguments? 
> `parent::__construct()` call in a descendant will appear broken 
> (unintentionally, I suppose), won't it?

If you introduce a mandatory parameter to *any* function, method, or 
constructor, existing calls to that function, method, or constructor 
will be broken.

A class with no defined constructor already behaves as if its 
constructor had no arguments when using "new", so introducing a 
constructor with mandatory arguments is already a breaking change.

-- 
Rowan Collins
[IMSoP]

---

## #78960 — Rowan Collins — 2014-11-18T21:51:11+00:00

URL: https://externals.io/message/78935#78960 · In reply to: #78949

> Hi!
>
> > […]
> Ah, but the former describes the option that has been *rejected*. The
> option that was chosen instead does not have the BC break.
>

Personally, I would much prefer the backwards compatibility break to 
happen. It is frankly quite bizarre, and not at all useful, that the 
following two pieces of code behave differently:

class Foo {}
new Foo( print('hello') );
// silent

vs

class Foo { function __construct() {} }
new Foo( print('hello') );
// says "hello"

(Incidentally, HHVM doesn't have this "optimisation", and says "hello" 
in both cases: http://3v4l.org/ZDXs1)

If I came upon this without knowing more, I would assume it was a bug in 
PHP, and any code relying on it was in need of fixing ASAP.

Regards,

-- 
Rowan Collins
[IMSoP]

---

## #78961 — Andrea Faulds — 2014-11-18T21:53:37+00:00

URL: https://externals.io/message/78935#78961 · In reply to: #78960

> 
> 
> Personally, I would much prefer the backwards compatibility break to happen. It is frankly quite bizarre, and not at all useful, that the following two pieces of code behave differently:
> 
> class Foo {}
> new Foo( print('hello') );
> // silent
> 
> vs
> 
> class Foo { function __construct() {} }
> new Foo( print('hello') );
> // says "hello"
> 
> (Incidentally, HHVM doesn't have this "optimisation", and says "hello" in both cases: http://3v4l.org/ZDXs1)
> 
> If I came upon this without knowing more, I would assume it was a bug in PHP, and any code relying on it was in need of fixing ASAP.

In fact, it *is* a bug: https://bugs.php.net/bug.php?id=67829

--
Andrea Faulds
http://ajf.me/

---

## #78962 — Markus Fasselt — 2014-11-18T22:18:29+00:00

URL: https://externals.io/message/78935#78962 · In reply to: #78952

Hi!

> Making everything descend from the same class may require a number of
> changes and much bigger design effort than this RFC aims at, with wider
> BC implications.

I am not sure, whether this might be a problem (I am just starting to
dive into PHP internals), but I can think of constructor visibility
problems. What visibility should the main constructor have?
If it is public (or protected), you can't have private constructors
anylonger

> Fatal error: Access level to Foo::__construct() must be public (as in
class BaseClass)

So there have to be changes in the validation of a class and in the
instantiation to not get this problem. Don't know whether this is a
bigger concern, but I just got this idea.

---

## #78963 — Stanislav Malyshev — 2014-11-18T22:54:25+00:00

URL: https://externals.io/message/78935#78963 · In reply to: #78961

Hi!

> In fact, it *is* a bug: https://bugs.php.net/bug.php?id=67829

It is most definitely not a bug, it's the intended behavior that has
been coded so and has been in PHP for a very long time. You may argue it
should not be so, and it should be changed, that's fine, but it's not
what is called a bug - it's not a mistake, it's how it was intended to
work. Changing this is a feature request, for which you're welcome to
make an RFC. I'm not sure though it would be very useful change since
IMO it would break BC for no actual gain to any practical code. But if
you think you're wrong RFC is definitely an option.

---

## #78964 — Rowan Collins — 2014-11-18T22:56:41+00:00

URL: https://externals.io/message/78935#78964 · In reply to: #78961

> > […]
> In fact, it *is* a bug: https://bugs.php.net/bug.php?id=67829

Or, depending on who looks at the report, it's Not A Bug: 
https://bugs.php.net/bug.php?id=54162

But, yes, I would argue that both reports are actually valid, and this 
behaviour, however long-standing, is an accident of implementation, not 
a design decision that anyone can actually justfiy.

Regards,

-- 
Rowan Collins
[IMSoP]

---

## #78965 — Andrea Faulds — 2014-11-18T22:57:43+00:00

URL: https://externals.io/message/78935#78965 · In reply to: #78963

> 
> 
> Hi!
> 
> > […]
> 
> It is most definitely not a bug, it's the intended behavior that has
> been coded so and has been in PHP for a very long time. You may argue it
> should not be so, and it should be changed, that's fine, but it's not
> what is called a bug - it's not a mistake, it's how it was intended to
> work.

Are you sure it was intended to work this way, with the parameters not being evaluated at all? Is that actually useful in any context? Function calls always evaluate their arguments, do they not? PHP is a language with functions that have side effects.

> Changing this is a feature request, for which you're welcome to
> make an RFC. I'm not sure though it would be very useful change since
> IMO it would break BC for no actual gain to any practical code. But if
> you think you're wrong RFC is definitely an option.

Alright then, it’s a “feature” that needs fixing, not a bug.
--
Andrea Faulds
http://ajf.me/

---

## #78966 — Rowan Collins — 2014-11-18T23:06:16+00:00

URL: https://externals.io/message/78935#78966 · In reply to: #78963

> It is most definitely not a bug, it's the intended behavior that has
> been coded so and has been in PHP for a very long time. You may argue it
> should not be so, and it should be changed, that's fine, but it's not
> what is called a bug - it's not a mistake, it's how it was intended to
> work.

"Been in PHP for a very long time" != "how it was intended to work". Can 
you explain why this would be the intention of anyone designing the 
language?

It seems to me that it is an unforeseen side effect of a different 
feature - that when raising a Fatal Error for a non-existent function or 
method, the runtime bails out immediately, without bothering to evaluate 
the arguments. That's very different from a non-existent constructor 
call *successfully executing* without its parameters being evaluated.

It's a mistake that was made a long time ago, and nobody's thought it 
worth the effort to fix, but it's still a mistake, IMHO.

-- 
Rowan Collins
[IMSoP]

---

## #78968 — Stanislav Malyshev — 2014-11-18T23:11:02+00:00

URL: https://externals.io/message/78935#78968 · In reply to: #78966

Hi!

> "Been in PHP for a very long time" != "how it was intended to work". Can
> you explain why this would be the intention of anyone designing the
> language?

Of course, been for a long time is not the same as intended. But if you
look at how ZEND_NEW is done, it's clear it's intended. And the reason
is simple - if there's no function, it's not really possible to initiate
a function call and handle it properly, since the engine expects certain
data there and there's nothing to provide that data. So, ZEND_NEW having
no function just skips the whole function call thing altogether.

> It's a mistake that was made a long time ago, and nobody's thought it
> worth the effort to fix, but it's still a mistake, IMHO.

It's not a mistake - at least, not an unintentional one, it was a
decision. If you think the decision was wrong and it can be done better
- cool, let's see the patch.

---

Next page: https://externals.io/message/78935.md?page=2
