rfc:code_free_constructor

Differences

This shows you the differences between two versions of the page.

Link to this comparison view

Both sides previous revision Previous revision
Next revision
Previous revision
rfc:code_free_constructor [2019/01/16 14:51]
rjhdby
rfc:code_free_constructor [2019/01/29 12:17] (current)
rjhdby
Line 1: Line 1:
 ====== PHP RFC: Code free constructor ====== ====== PHP RFC: Code free constructor ======
-  * Version: 0.1 +  * Version: 0.2 
-  * Date: 2019-01-14+  * Date: 2019-01-29
   * Author: Andrey Gromov, andrewgrom@rambler.ru, rjhdby@php.net   * Author: Andrey Gromov, andrewgrom@rambler.ru, rjhdby@php.net
   * Proposed version: PHP 8   * Proposed version: PHP 8
-  * Status: Pre draft+  * Status: draft
   * First Published at: https://wiki.php.net/rfc/code_free_constructor   * First Published at: https://wiki.php.net/rfc/code_free_constructor
-  * ML thread: -+  * ML thread: https://externals.io/message/103793 
 + 
 +===== Changelog ===== 
 +**v 0.2**  
 +  * Added visibility modificators syntax. 
 +  * Changed behavior for parameters that need to be forwarded to parent. 
 +  * Added "anonymous class" section. 
 +  * Added "Q&A, Discussion" section. 
 +  * Improved description of realization.
  
 ===== Introduction ===== ===== Introduction =====
-Mainly "code free" constructors used for declaration of DTO-classes. +"Code free" constructor is constructor with only purpose to directly set object properties from received parameters and, optionally, call parent constructor. 
-Also, some developers believe that it is good OOP-practice. + 
-Unfortunately they looks like unnecessary boilerplate.+They used for
 +  * for DTO-classes declaration 
 +  developersthat believe it is good OOP-practice, use them everywhere 
 +  * useful in some cases of inheritance 
 + 
 +Unfortunately, php syntax enforces to write unnecessary boilerplate.
  
 ===== Proposal ===== ===== Proposal =====
 Proposal is to add alternate syntax for "code free" constructors. Proposal is to add alternate syntax for "code free" constructors.
 +
 +There is two generals parts of proposal.
 +
 +=== First. Automatic property initialization ===
 +
 Current syntax: Current syntax:
 <code php> <code php>
-class Test+class MotorCycle { 
-    public function __construct($first, $second){ +    protected $vendor; 
-        $this->first  = $first+    public $driver; 
-        $this->second = $second;+    private int $cc; 
 +     
 +    public function __construct(string $vendorPerson $driver, int $cc = 600) { 
 +        $this->vendor = $vendor; 
 +        $this->driver = $driver
 +        $this->cc     = $cc;
     }     }
-    ... 
 } }
 </code> </code>
Line 28: Line 50:
 Proposed syntax: Proposed syntax:
 <code php> <code php>
-class Test($first, $second){ +class MotorCycle(protected string $vendorPerson $driver, private int $cc = 600){ }; 
-    ...+</code> 
 +If no visibility modifier defined it casts as "public". 
 + 
 +Under the hood, at AST-creation phase, will be silently created right properties declaration and added "_ _ construct" method similar to showed aboveSo following compilation and runtime will work standard way. 
 + 
 +=== Second. Automatic passing args to parent constructor === 
 +For this example I will use class "MotorCycle" from previous section. 
 + 
 +Current syntax: 
 +<code php> 
 +class MyCustomMotorCycle extends MotorCycle { 
 +    public $passenger; 
 +     
 +    public function __construct(Person $driver, Person $passenger) { 
 +        parent::__construct("Custom", $driver); 
 +        $this->passenger = $passenger; 
 +    }
 } }
 </code> </code>
 +
 +Proposed syntax:
 +<code php>
 +class MyCustomMotorCycle(Person $driver, Person $passenger) 
 +    extends MotorCycle("Custom", $driver) { };
 +</code>
 +In this case, if some params must be forwarded to parent then they will not be declared and set in child. This behavior is disputable.
 +
 +Realisation is similar to described above with additional checks and parent call.
 +
 +Note that you can use all standard syntax constructions like default parameters and splat operator ("...")
 +
 +{{:rfc:joined.png?400|}}
 +
 +===== Anonymous classes =====
 +Since the syntax for declaring an anonymous class is what it is, the only option that I can imagine is not very beautiful.
 +
 +<code php>
 +$a = new class($mDriver, $mPassenger) extends MotorCycle {
 +    private $passenger;
 +    public function __construct(Person $driver, Person $passenger) {
 +        parent::__construct("Custom", $driver);
 +        $this->passenger = $passenger;
 +    }
 +};
 +
 +//            |------arguments------||-----------constructor params------------|
 +$a = new class($mDriver, $mPassenger)(Person $driver, private Person $passenger) 
 +        extends MotorCycle("Custom", $driver){};
 +</code>
 +
 +{{:rfc:anon.png}}
  
 ===== Backward Incompatible Changes ===== ===== Backward Incompatible Changes =====
-No.+Do not know. Looks like no BI.
  
 ===== Proposed PHP Version(s) ===== ===== Proposed PHP Version(s) =====
Line 41: Line 111:
 ===== RFC Impact ===== ===== RFC Impact =====
 Not thinking so Not thinking so
- 
-===== Future Scope ===== 
-Deal with parent's constructor call 
  
 ===== Implementation ===== ===== Implementation =====
-Draft implementation, need to be reviewed. 
-https://github.com/rjhdby/php-src/tree/constructor 
  
 +Draft implementation, need to be reviewed. **Outdated!**
 +https://github.com/rjhdby/php-src/compare/master...rjhdby:constructor
 +
 +===== Q&A, Discussion =====
 +**Stanislav Malyshev**<blockquote>This looks like unobvious magic. PHP approach has traditionally been to avoid unobvious magic, and be explicit about what is happening. This functionality does not seem no be enabling anything different, and seems to be pretty obscure as to what is going on. Also, $prop can not be documented this way, and assigning default value to it may be a bit weird too. I am all for paving the walkways, but this particular case seems to be a bit too narrow to have a special language syntax for, and the syntax seems to be not exactly obvious as to what's going on there.</blockquote>
 +
 +**Nikita Popov**<blockquote>Two alternatives you might want to consider:
 +
 +https://wiki.php.net/rfc/automatic_property_initialization 
 +=> Proposed function public function _ _ construct(int $this->x, int $this->y) {}, which avoids the need for explicit property assignments in the ctor. However, the property still needs to be declared separately.
 +
 +https://docs.hhvm.com/hack/other-features/constructor-parameter-promotion
 +=> Uses public function _ _ construct(public int $x, public int $y) {} to declare properties in-line in the constructor.
 +
 +I think that *if* we want to add some kind of sugar of this type, then I'd strongly prefer the syntax used by Hack than the one proposed here. It makes a lot more sense to me intuitively, probably because the property declarations still looks like normal property declarations, they just occur in-line in the ctor.</blockquote>
 +A matter of habit and documentation. There is a lot of really strange and magical behavior in the language. It seems to me that the proposed concept is quite simple and transparent for understanding. IMHO this syntax make behavior more strict. No need to 
 +read constructor's body, because you know exactly what's going on.
 ===== References ===== ===== References =====
  
  
rfc/code_free_constructor.1547650312.txt.gz · Last modified: 2019/01/16 14:51 by rjhdby