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
-----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 constructorsHi!
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);
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
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
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 itObviously, 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/
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.
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 itObviously, 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.
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.
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]
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
Hi!
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.
Ah, but the former describes the option that has been rejected. The
option that was chosen instead does not have the BC break.
Hi!
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.
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]
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') );
// silentvs
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/
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.
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.
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/
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]
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.
"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.
This is where I struggle: to me, the "++$b" in "foo(++$b)" or "new
Foo(++$b)" isn't part of the function call; it's a statement that has to
be evaluated before the function call can happen.
If a fatal error is being raised, it makes (some) sense to skip that
evaluation, but if execution is continuing, it seems perfectly natural
for that expression to be evaluated even if its result is discarded.
If you think the decision was wrong and it can be done better
- cool, let's see the patch.
I'm happy to accept that this is a low-priority, hard-to-fix, bug. I
just don't see that it can be justified as a feature.
--
Rowan Collins
[IMSoP]
If a fatal error is being raised, it makes (some) sense to skip that
evaluation
To be honest, it's a little weird to me that these two programs behave
differently:
$a = print('hello');
non_existent_function($a);
vs
non_existent_function( print('hello') );
But relying on the exact behaviour during a fatal error would certainly
be ill-advised.
--
Rowan Collins
[IMSoP]
Hi!
I'm happy to accept that this is a low-priority, hard-to-fix, bug. I
just don't see that it can be justified as a feature.
We can argue semantics of the word "bug" all day long, but the fact is
the functionality as it is is there by an explicit decision - it was
chosen to be this way and no other way, for the reasons I have
described, it was no omission and no unintended side-effect of
something, it was meant to work this way. If you want to call it "hard
to fix bug" knowing this, you're welcome to.
Hi!
I'm happy to accept that this is a low-priority, hard-to-fix, bug. I
just don't see that it can be justified as a feature.We can argue semantics of the word "bug" all day long, but the fact is
the functionality as it is is there by an explicit decision - it was
chosen to be this way and no other way, for the reasons I have
described, it was no omission and no unintended side-effect of
something, it was meant to work this way. If you want to call it "hard
to fix bug" knowing this, you're welcome to.
Is there a .phpt
test-case or discussion backing this?
I find this quite hard to believe, especially since following examples are
broken in php and working "as expected" (by me) in hhvm:
http://3v4l.org/4nhoq
Yes, that's a bug :-)
Marco Pivetta
Hi!
Is there a
.phpt
test-case or discussion backing this?
Backing what? Checking if side effects happen when evaluating args of
non-existing ctor? Probably not, since nobody ever needed it (correct me
if I'm wrong). There are many weird scenarios of what you could do with
PHP that are not covered by tests because nobody ever thought anybody
would care to know what happens if you do that.
But I don't need tests to conclude it's intentional behavior - plain
look at the code shows it very clearly, you don't make special case in
ZEND_NEW to skip the ctor method call and write all the code around it
if you don't mean to make special case to do just that.
I find this quite hard to believe, especially since following examples
are broken in php and working "as expected" (by me) in hhvm:
http://3v4l.org/4nhoqYes, that's a bug :-)
No, it is not :)
We can do it all day but I think I've explained what is going on there.
If you want to change it, feel free to do the RFC.
Hi!
Is there a
.phpt
test-case or discussion backing this?Backing what? Checking if side effects happen when evaluating args of
non-existing ctor? Probably not, since nobody ever needed it (correct
me
if I'm wrong).
Quite: nobody ever needed, or expected it, or intended it.
There are many weird scenarios of what you could do with
PHP that are not covered by tests because nobody ever thought anybody
would care to know what happens if you do that.
Fine. And some of those edge cases, when tested, do the wrong thing. Those are bugs.
But I don't need tests to conclude it's intentional behavior - plain
look at the code shows it very clearly, you don't make special case in
ZEND_NEW to skip the ctor method call and write all the code around it
if you don't mean to make special case to do just that.
I still don't have enough understanding of the engine to follow the argument here. That the engine skips code to dispatch to a non-existent __construct method doesn't seem on the face of it proof that lazy evaluation of its arguments was intended. It sounds more like an implementation detail that skipping a function dispatch also happens to skip evaluation of those expressions.
There is nowhere else in the language which lazily evaluates the arguments of a function based on the content of that function. Unused parameters, including those passed to an empty constructor, are always evaluated. I'm not sure why you're treating a parameter expression with side effects as something exotic.
Yes, that's a bug :-)
No, it is not :)
We can do it all day but I think I've explained what is going on there.
If you want to change it, feel free to do the RFC.
The point of this discussion is that there is an RFC on the table which can be implemented in such a way that it fixes this behaviour (by introducing a default parent, or injecting an empty constructor) or such that it carefully preserves it (by making a special case for parent::__construct).
If you are, as you seem to be, defending this as a feature, it implies we should preserve (and, incidentally, standardise) it. If, as I and others argue, it was only ever an unintended effect of the implementation, then we should take the opportunity to correct it.
This reminds me of the recent discussion over multiple defaults in a switch. Perhaps as with that we should phrase the question as "is there any useful purpose to having the language standardised with this feature, and conversely is there any realistic harm in altering it?"
Hi!
The point of this discussion is that there is an RFC on the table
which can be implemented in such a way that it fixes this behaviour
(by introducing a default parent, or injecting an empty constructor)
or such that it carefully preserves it (by making a special case for
parent::__construct).
I was not planning to do this as part of this RFC. Of course, that
doesn't mean by itself it should not be done, and if it will be done
(after considering all BC consequences, etc.) then the code for this RFC
will need to be changed (while the idea stays). But I do not want to mix
two things - making parent methods always work in places where it makes
sense (ctor, dtor, clone) and refactoring how ctors work to avoid
unpleasant side effect of not evaluating params for missing ctor. These
are two different things, with different consequences, and I don't see
much win in mixing them.
If you are, as you seem to be, defending this as a feature, it
implies we should preserve (and, incidentally, standardise) it. If,
No, not really - I don't propose to standardize it. I do propose to
preserve it, for basic BC reasons, and I do say it was an intended
result, not an accidental omission. Now, this result, of course, can be
what we no longer want, and we can change it - but I don't want to make
it a part of my RFC because I consider it an independent issue worthy of
separate consideration.
This reminds me of the recent discussion over multiple defaults in a
switch. Perhaps as with that we should phrase the question as "is
there any useful purpose to having the language standardised with
this feature, and conversely is there any realistic harm in altering
it?"
You make it sound as if I'm somehow calling for some change in
"standardizing" this feature. On the contrary, I am just preserving the
status quo, it is as "standard" or "non-standard" as it has ever been.
Somehow HHVM has this working http://3v4l.org/5AFSA
Hi!
The point of this discussion is that there is an RFC on the table
which can be implemented in such a way that it fixes this behaviour
(by introducing a default parent, or injecting an empty constructor)
or such that it carefully preserves it (by making a special case for
parent::__construct).
I was not planning to do this as part of this RFC. Of course, that
doesn't mean by itself it should not be done, and if it will be done
(after considering all BC consequences, etc.) then the code for this RFC
will need to be changed (while the idea stays). But I do not want to mix
two things - making parent methods always work in places where it makes
sense (ctor, dtor, clone) and refactoring how ctors work to avoid
unpleasant side effect of not evaluating params for missing ctor. These
are two different things, with different consequences, and I don't see
much win in mixing them.If you are, as you seem to be, defending this as a feature, it
implies we should preserve (and, incidentally, standardise) it. If,
No, not really - I don't propose to standardize it. I do propose to
preserve it, for basic BC reasons, and I do say it was an intended
result, not an accidental omission. Now, this result, of course, can be
what we no longer want, and we can change it - but I don't want to make
it a part of my RFC because I consider it an independent issue worthy of
separate consideration.This reminds me of the recent discussion over multiple defaults in a
switch. Perhaps as with that we should phrase the question as "is
there any useful purpose to having the language standardised with
this feature, and conversely is there any realistic harm in altering
it?"
You make it sound as if I'm somehow calling for some change in
"standardizing" this feature. On the contrary, I am just preserving the
status quo, it is as "standard" or "non-standard" as it has ever been.
--
Regards,
Bradley.
Direct: 0116 224 7372
Office: 0845 004 0662
Mobile: 07902 672289
E-Mail: brad@legalweb.org.uk
WebSite: legalweb.org.uk
This message is intended only for the use of person(s) ("the Intended Recipient") to whom it is addressed. It may contain information that is privileged and confidential within the meaning of applicable law. Accordingly any dissemination, distribution, copying or other use of this message or any of its content by any other person may constitute a breach of civil or criminal law and is strictly prohibited. If you are not the Intended Recipient please contact the sender as soon as possible. Any views expressed in this message are those of the individual sender and may not necessarily reflect the views of Legalwebb UK Ltd or any of its subsidiary businesses. Legalwebb UK Limited is Registered in Cardiff. Company Number 03874311. Registered for VAT Number 803886708
On Thu, Nov 20, 2014 at 9:44 AM, Bradley Weston bradley@legalweb.org.uk
wrote:
Somehow HHVM has this working http://3v4l.org/5AFSA
it was mentioned early in the thread that hhvm is not copying the behavior
of php for optimizing out the execution of the argument if the constructor
doesn't except one.
--
Ferenc Kovács
@Tyr43l - http://tyrael.hu
Stanislav Malyshev wrote on 20/11/2014 00:44:
This reminds me of the recent discussion over multiple defaults in a
switch. Perhaps as with that we should phrase the question as "is
there any useful purpose to having the language standardised with
this feature, and conversely is there any realistic harm in altering
it?"
You make it sound as if I'm somehow calling for some change in
"standardizing" this feature. On the contrary, I am just preserving the
status quo, it is as "standard" or "non-standard" as it has ever been.
Well, as others have pointed out, HHVM behaves differently in this case,
so I guess what I'm getting at is: is this considered a feature of the
language, or just a known oddity of the implementation? If it's part
of the language, it should be standardised in the language spec, so that
other implementations can emulate it (or decide to deviate from it); if
not, then it seems appropriate to talk of "fixing" rather than
"changing" it.
--
Rowan Collins
[IMSoP]
Hi!
Well, as others have pointed out, HHVM behaves differently in this case,
And?
so I guess what I'm getting at is: is this considered a feature of the
language, or just a known oddity of the implementation? If it's part
I do not think the standard should require it, as whoever using this for
anything, one way or another, is doing it very, very wrong, but that's
how it works now.
other implementations can emulate it (or decide to deviate from it); if
not, then it seems appropriate to talk of "fixing" rather than
"changing" it.
The choice of emotionally charged term is up to whoever uses it, my
point was just that this was a deliberate intentional decision, not an
unintentional mistake, and any change there has BC consequences. I think
this point is well made by now, so unless there is something new to say,
I'll refrain from discussing it further.
Stas Malyshev
smalyshev@gmail.com
Stanislav Malyshev wrote on 20/11/2014 18:47:
I do not think the standard should require it, as whoever using this for
anything, one way or another, is doing it very, very wrong, but that's
how it works now.
As I said before, I don't see anything "very, very wrong" about assuming
that this code will increment $b, and run function bar():
$foo = new Foo(++$b);
$foo = new Foo( bar() );
The fact that I need to know the internals of class Foo to know whether
it will is pretty weird in a language which has no other lazy evaluation.
If it was the fact the constructor had insufficient parameters that
triggered the laziness, it would be less surprising; but adding a
constructor with no parameters, and an empty body, causes the expression
to be evaluated, even though its result is still thrown away, and the
public API of class Foo is identical.
Intentional or not, I think this is undesirable behaviour, and if it can
be changed without too much difficulty, it should be.
Rowan Collins
[IMSoP]
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') );
// silentvs
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
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]
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/
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 JavaObject
?
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
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 JavaObject
?
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/
Andrea Faulds wrote on 18/11/2014 13:11:
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 JavaObject
?
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.
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]
Hi!
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
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.
Anthony pointed out last time, you can't do inheritance and
simultaneously treat the parent class as a black box.
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.
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.
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
Hi Stas,
Sorry, I didn't follow all the discussions.
I think the idea is good.
I'm not sure about implementation.
Additional check for ZEND_NULL_FUNCTION in DO_FCALL may be expensive.
I think it must be better to use special predefined function (see
"zend_pass_function" usage in zend_vm_def.h).
Thanks. Dmitry.
On Tue, Nov 18, 2014 at 12:20 PM, 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!
I think the idea is good.
I'm not sure about implementation.
Additional check for ZEND_NULL_FUNCTION in DO_FCALL may be expensive.
I think it must be better to use special predefined function (see
"zend_pass_function" usage in zend_vm_def.h).
I've moved the condition after internal & user function, so the slowdown
would almost never happen and will be very minimal. But if you prefer, I
can do the other one, I actually implemented it first with the function
but then removed it since I thought ability to skip a function call may
be faster and also prove useful in other cases. I'll try to do another
version with zend_pass_function and see if I see any difference.
--
Stas Malyshev
smalyshev@gmail.com
Hi!
Additional check for ZEND_NULL_FUNCTION in DO_FCALL may be expensive.
I think it must be better to use special predefined function (see
"zend_pass_function" usage in zend_vm_def.h).
I've made a different implementation here:
https://github.com/smalyshev/php-src/compare/php:master...smalyshev:default_ctor_func?expand=1
which uses zend_pass_function but I had to make it static since
otherwise it's increase refcount for object and it doesn't seem like it
decrements back. So I'm not sure if it's right, what do you think?
--
Stas Malyshev
smalyshev@gmail.com
thanks Stas. I'll think on next week.
Dmitry.
On Fri, Nov 21, 2014 at 6:59 AM, Stanislav Malyshev smalyshev@gmail.com
wrote:
Hi!
Additional check for ZEND_NULL_FUNCTION in DO_FCALL may be expensive.
I think it must be better to use special predefined function (see
"zend_pass_function" usage in zend_vm_def.h).I've made a different implementation here:
https://github.com/smalyshev/php-src/compare/php:master...smalyshev:default_ctor_func?expand=1
which uses zend_pass_function but I had to make it static since
otherwise it's increase refcount for object and it doesn't seem like it
decrements back. So I'm not sure if it's right, what do you think?--
Stas Malyshev
smalyshev@gmail.com
I like the last patch. I think ZEND_ACC_STATIC flag must not make any
problems.
However, I thought about one more inconsistent. Your patch works fine for
"parent::" methods but not for "grandparents::"
In the following code "default constructor" won't work.
class A {
}
class B extends A {
}
class C extends B {
function __constructor() {
A::_constructor(); // this won't work
}
}
It's not a big problem to fix implementation to support it, or may be
support for "parent::" is enough.
Anyway, it should be reflected in RFC (if this code should work or should
not).
Thanks. Dmitry.
thanks Stas. I'll think on next week.
Dmitry.
On Fri, Nov 21, 2014 at 6:59 AM, Stanislav Malyshev smalyshev@gmail.com
wrote:Hi!
Additional check for ZEND_NULL_FUNCTION in DO_FCALL may be expensive.
I think it must be better to use special predefined function (see
"zend_pass_function" usage in zend_vm_def.h).I've made a different implementation here:
https://github.com/smalyshev/php-src/compare/php:master...smalyshev:default_ctor_func?expand=1
which uses zend_pass_function but I had to make it static since
otherwise it's increase refcount for object and it doesn't seem like it
decrements back. So I'm not sure if it's right, what do you think?--
Stas Malyshev
smalyshev@gmail.com
Dmitry Stogov wrote on 24/11/2014 09:56:
However, I thought about one more inconsistent. Your patch works fine for
"parent::" methods but not for "grandparents::"
In the following code "default constructor" won't work.class A {
}
class B extends A {
}
class C extends B {
function __constructor() {
A::_constructor(); // this won't work
}
}
I guess some inconsistency like this is hard to avoid unless the default
constructor is actually added to the class's method table, because the
code has to specifically check for each case that is to be supported.
At risk of flogging a dead horse, this is why I was arguing for the lazy
evaluation with new keyword to be abandoned, because it seems like
that's the primary compatibility issue with adding a "real" default
definition. Reflection would show the method as either "internal" or
inherited from some implicit base class.
From a user's point of view there should really be no difference
between "no constructor" and "constructor which does nothing", IMHO.
Regards,
Rowan Collins
[IMSoP]
Hi!
However, I thought about one more inconsistent. Your patch works fine
for "parent::" methods but not for "grandparents::"
In the following code "default constructor" won't work.
Yes, this is OK - the support is only for one pattern, calling the
parent, because it's what you're supposed to do. If you do anything
else, it would work (or not work) as before since it's not the best
practice so you're on your own.
It's not a big problem to fix implementation to support it, or may be
support for "parent::" is enough.
Anyway, it should be reflected in RFC (if this code should work or
should not).
Sure, I'll add a note on RFC about it.
Stas Malyshev
smalyshev@gmail.com