Req #71419 [Com]: Allow ::new() syntax.
| From: | marcio@php.net | Date: | Fri, 11 Mar 2016 05:45:08 +0000 |
| Subject: | Req #71419 [Com]: Allow ::new() syntax. | ||
| References: | 1 | Groups: | php.bugs |
| Request: | Send a blank email to php-bugs+get-199748@lists.php.net to get a copy of this message | ||
Edit report at https://bugs.php.net/bug.php?id=71419&edit=1
ID: 71419
Comment by: marcio@php.net
Reported by: andreas at dqxtech dot net
Summary: Allow ::new() syntax.
Status: Open
Type: Feature/Change Request
Package: Class/Object related
PHP Version: 7.0.2
Block user comment: N
Private report: N
New Comment:
Hi!
The main reason that could make a default ::new() method impracticable, at least to my POV, is that
__construct() doesn't follow the 'normal' inheritance rules from other methods (see
https://3v4l.org/LeaZ1), a default ::new() method would have to
be special cased too and therefore would require a 'magic' behavior.
How should ::new() behave when a third party class __construct requires parameters in order to
instantiate an usable instance? Consider:
class ImmutableArray {
private $data = [];
function __construct(array $data) {
$this->data = $data;
}
/* then other methods to read $this->data */
}
So far this is what I've been questioning:
- Would ::new() always instantiate an empty (and useless) ImmutableArray?
- Would it be necessary to implement ::new() to ::new(array $data) so it follows the same spec of
__construct(array $data)?
- Would we be able to overwrite ::new() at all?
I'd love to have ::new() from day 1 php was designed but now, unfortunately, having
__construct() and ::new() on first class at the same time creates more issues than it should even
though there is beauty in symmetry :/
Previous Comments:
------------------------------------------------------------------------
[2016-02-04 00:56:59] andreas at dqxtech dot net
> You're asking for a factory method as a built-in language construct/feature.
Yes, what you describe is exactly what I mean.
> If your reasoning lies strictly on method chaining, static methods (factory or not) is a
> language feature you should use.
But then I need to manually add this to every class. What if the class is from a 3rd party?
And does the DX benefit really justify adding empty static methods everywhere?
This is why I am looking for a build-in, implicit static method.
(you could now ask back, whether this justifies a new language feature.. which is debatable, of
course)
> The primary difference between "C::new()" and "(new C())" is one character
> less in length.
The benefit is not in typing one character less, but:
- It becomes easier to switch between a static factory call and a new() call.
- If you don't know yet whether the class has a static factory method and/or a public
constructor, you can start typing the class name and then have the IDE suggest the different
options.
- You no longer need to think about adding or not adding the round brackets for method chaining.
Yes, this is only about DX, which is obviously debatable.
Examples:
Replacing "C::new()" with "C::create()" is easier than replacing "(new
C())" with "C::create()".
Extending "C::new()" to "C::new()->foo()" is easier than extending "new
C()" to "(new C())->foo()".
Reducing "C::new()->foo()" to C::new() is easier than reducing "(new
C())->foo() to "new C()".
C::new()
to
C::new()
->foo()
is only one line of diff.
new C()
to
(new C())
->foo()
is two lines of diff.
> At best, that will lead to a slippery-slope (e.g. I'd like C::delete to call C::__destruct
> - even though I can just use $instance = null or unset($instance)).
Yes, it would be interesting if there are other keywords where this makes sense. But so far I cannot
think of any. C::delete($object) is really not useful, because the class can already be determined
from $object.
Another examples could be C::reflection() (to create a new reflection class). But I don't think
this is as big a use case that it justifies a new language feature.
The refactoring from (new C()) to (C::create()), on the other hand, is something I come across all
the time.
> If you feel strongly about this, you should write up an RFC, and put it out there for
> discussion.
Will see.
------------------------------------------------------------------------
[2016-02-01 16:00:07] willfitch@php.net
> Proposal: Allow a syntax "C::new()", which would be equivalent to "(new
> C())"
You're asking for a factory method as a built-in language construct/feature. While I won't
assume your situation warrants this in your opinion, I have/can never imagine why this is warranted.
If your reasoning lies strictly on method chaining, static methods (factory or not) is a language
feature you should use.
The primary difference between "C::new()" and "(new C())" is one character less
in length. Looking at this from a purely language perspective, you're essentially asking for
an exception to a static method call. At best, that will lead to a slippery-slope (e.g. I'd
like C::delete to call C::__destruct - even though I can just use $instance = null or
unset($instance)).
If you feel strongly about this, you should write up an RFC, and put it out there for discussion.
You won't get much traction in the bugs area.
------------------------------------------------------------------------
[2016-01-25 15:54:49] andreas at dqxtech dot net
I think before accepting the RFC it would have been a good idea to check which of these reserved
words could have a useful meaning with "::", and thus, which doors are being closed by
allowing these keywords as method names.
E.g. for C::while() I don't really see anything useful other than interpreting it as a method.
So it is fine to make "while" a valid method name.
For C::new(), this could be an alternative syntax for "new C()". So maybe a good idea to
keep this reserved..
C::class already has a meaning. C::namespace could be given a meaning.
For now, C::new() is the only one that sticks out to me for method syntax.
------------------------------------------------------------------------
[2016-01-25 15:44:49] andreas at dqxtech dot net
Thanks for the RFC link!
> Anyway, you could use a trait to make your wished pattern easier to implement (on 7.0+):
Sure.. but of course the idea here was to make this a language feature, so it would work for all
classes, including those from 3rd party libraries, where I cannot add a "use Newable".
I guess it is not going to happen.
------------------------------------------------------------------------
[2016-01-25 15:36:38] wegvonhier+phpbugs at gmail dot net
I believe the correspondig rfc for that change is this one: https://wiki.php.net/rfc/context_sensitive_lexer
(allowing reserved words such as new in more contexts, the rfc even has an example using
Collection::new()->method())
Anyway, you could use a trait to make your wished pattern easier to implement (on 7.0+):
https://3v4l.org/ZQLSk
------------------------------------------------------------------------
The remainder of the comments for this report are too long. To view
the rest of the comments, please view the bug report online at
https://bugs.php.net/bug.php?id=71419
--
Edit this bug report at https://bugs.php.net/bug.php?id=71419&edit=1