Req #71419 [Opn]: Allow ::new() syntax.

From: Date: Thu, 04 Feb 2016 00:57:03 +0000
Subject: Req #71419 [Opn]: Allow ::new() syntax.
References: 1  Groups: php.bugs 
Request: Send a blank email to php-bugs+get-199040@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 User updated by: andreas at dqxtech dot 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: > 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. Previous Comments: ------------------------------------------------------------------------ [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 ------------------------------------------------------------------------ [2016-01-20 13:06:05] andreas at dqxtech dot net Description: ------------ I often create classes that have a normal constructor, and one or more static factory methods. On instantiation, I need to decide between "new C()" and "C::create()". For method chaining, the "new C()" needs additional brackets, like so: "(new C())". Switching between the two notations can be annoying. Proposal: Allow a syntax "C::new()", which would be equivalent to "(new C())". -------- Now.. when I had this idea, I was not aware that since PHP 7, and also in hhvm, it is possible to name a method like "new()". https://3v4l.org/Pp68v with user-defined method new(). https://3v4l.org/YvjJ9 without such a method. This is unfortunate, and makes this request difficult, if not impossible. A remaining (but not really great) option would be to give every class an "implicit" static method ::new(), but allow this method to be overridden. Maybe this was already discussed and discarded, and this is the reason why a method named "new()" is now allowed. In this case I would like this to be considered a support request. The answer could be a link to the discussion where this was decided. Test script: --------------- <?php class C {} class D { /** * Allowed since PHP 7 */ static function new() {return NULL;} } // Call implicit method new, equivalent to "new C()"; $instance = C::new(); assert($instance instanceof C); // Call explicit method new. $null = D::new(); assert($null === null); ------------------------------------------------------------------------ -- Edit this bug report at https://bugs.php.net/bug.php?id=71419&edit=1

« previous php.bugs (#199040) next »