rfc:property-capture
Differences
This shows you the differences between two versions of the page.
Both sides previous revisionPrevious revisionNext revision | Previous revisionNext revisionBoth sides next revision | ||
rfc:property-capture [2023/04/22 20:50] – imsop | rfc:property-capture [2023/04/23 18:54] – imsop | ||
---|---|---|---|
Line 24: | Line 24: | ||
Rather than inventing new syntax and semantics for these, this proposal reuses existing object properties and constructor parameters, as follows: | Rather than inventing new syntax and semantics for these, this proposal reuses existing object properties and constructor parameters, as follows: | ||
- | - If a use clause is present, generate an empty constructor which will be added to the anonymous class. | + | - If a '' |
- | - For each captured variable in the use clause, add it as a parameter to the constructor. | + | - For each captured variable in the '' |
- | - Declare a property with the same name as the captured variable in the anonymous class, unless renamed in the use clause (see below). | + | - Declare a property with the same name as the captured variable in the anonymous class, unless renamed in the '' |
- | - Set the default visibility of the property to '' | + | - Set the default visibility of the property to '' |
- In the constructor body, assign the captured variable to the corresponding property. | - In the constructor body, assign the captured variable to the corresponding property. | ||
- When creating an // | - When creating an // | ||
Line 35: | Line 35: | ||
===== Syntax ===== | ===== Syntax ===== | ||
- | A new "use clause" | + | A new //'' |
==== Basic Form ==== | ==== Basic Form ==== | ||
Line 152: | Line 152: | ||
echo $anon-> | echo $anon-> | ||
</ | </ | ||
+ | |||
+ | ===== Examples ===== | ||
+ | |||
+ | **TODO - expand** | ||
+ | |||
+ | Create a struct-like object with readonly public properties: | ||
+ | |||
+ | <code php> | ||
+ | $id = get_next_id(); | ||
+ | $name = get_name(); | ||
+ | $user = new readonly class use ($id, $name) {}; | ||
+ | echo " | ||
+ | $user-> | ||
+ | </ | ||
+ | |||
+ | Decorate a [[https:// | ||
+ | |||
+ | <code php> | ||
+ | use Psr\Log\{LoggerInterface, | ||
+ | |||
+ | function decorate_logger(LoggerInterface $logger, string $contextKey, | ||
+ | | ||
+ | use ($logger as private $innerLogger, | ||
+ | implements LoggerInterface | ||
+ | { | ||
+ | public function log($level, string|\Stringable $message, array $context = []): void { | ||
+ | $context[$this-> | ||
+ | $this-> | ||
+ | } | ||
+ | }; | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | ===== Reflection ===== | ||
+ | |||
+ | The constructor, | ||
+ | |||
+ | * '' | ||
+ | * '' | ||
+ | |||
+ | Although internally they are declared using Constructor Property Promotion, the parameters and properties return '' | ||
+ | |||
+ | The generated constructor itself is not marked, partly due to implementation concerns that a limited number of bits remain available in the '' | ||
===== Restrictions ===== | ===== Restrictions ===== | ||
Line 196: | Line 239: | ||
<code php> | <code php> | ||
- | # NOT supported in proposal | + | # NOT supported in current |
$anon = new class($b, $c) use($a) extends SomeOtherClass { | $anon = new class($b, $c) use($a) extends SomeOtherClass { | ||
public function __construct($b, | public function __construct($b, | ||
Line 217: | Line 260: | ||
<code php> | <code php> | ||
- | # NOT supported in proposal | + | # NOT supported in current |
$anon = new class($foo) use($bar) extends SomeOtherClass {}; | $anon = new class($foo) use($bar) extends SomeOtherClass {}; | ||
</ | </ | ||
Line 225: | Line 268: | ||
<code php> | <code php> | ||
$anon = new class($foo, $bar) extends SomeOtherClass { | $anon = new class($foo, $bar) extends SomeOtherClass { | ||
- | | + | |
public function __construct($foo, | public function __construct($foo, | ||
$this-> | $this-> | ||
Line 244: | Line 287: | ||
==== Alternative 3: Generating a Different Method ==== | ==== Alternative 3: Generating a Different Method ==== | ||
- | ==== Alternative 4: Calling an Additional Magic Method ==== | + | Similar to the workaround above, the logic for setting captured property values could be generated in a method other than the constructor, |
- | ===== Reflection ===== | + | That is, compile < |
- | The constructor, | + | <code php> |
+ | $anon = new class { | ||
+ | var $foo; | ||
+ | public function __capture($foo) { | ||
+ | $this-> | ||
+ | } | ||
+ | }; | ||
+ | $anon-> | ||
+ | </ | ||
- | * '' | + | That would allow this: |
- | * '' | + | |
- | Although internally they are declared using Constructor Property Promotion, the parameters and properties return '' | + | <code php> |
+ | # NOT supported in current proposal | ||
+ | $anon = new class($b, $c) use($a) extends SomeOtherClass { | ||
+ | public function __construct($b, | ||
+ | do_something($b); | ||
+ | parent::__construct($c); | ||
+ | } | ||
+ | }; | ||
+ | </ | ||
- | The generated constructor itself is not marked, partly due to implementation concerns that a limited number of bits remain available | + | To be equivalent |
+ | |||
+ | <code php> | ||
+ | $anon = new class($b, $c) extends SomeOtherClass { | ||
+ | var $a; | ||
+ | public function __construct($b, | ||
+ | do_something($b); | ||
+ | parent:: | ||
+ | } | ||
+ | public function __capture($a) { | ||
+ | $this->a = $a; | ||
+ | } | ||
+ | }; | ||
+ | $anon-> | ||
+ | </ | ||
+ | |||
+ | The main complexity here is generating the additional method call - in the above example, it is shown as called on the local variable | ||
+ | |||
+ | ==== Alternative 4: Calling an Additional Magic Method ==== | ||
+ | |||
+ | Another variation would be to have the constructor generated as in the current implementation, | ||
+ | |||
+ | <code php> | ||
+ | public function __construct($foo) { | ||
+ | $this-> | ||
+ | if ( method_exists($this, | ||
+ | $this-> | ||
+ | } | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | If arguments are not supported, the advantage of this over existing workarounds is very slight. If they are supported, it would run into many of the same difficulties outlined in previous sections. | ||
===== Backward Incompatible Changes ===== | ===== Backward Incompatible Changes ===== | ||
Line 273: | Line 362: | ||
None anticipated, | None anticipated, | ||
+ | ===== Unaffected Functionality ===== | ||
+ | |||
+ | All existing features of anonymous classes are retained, and can be combined with the new '' | ||
+ | |||
+ | * Inheriting parent classes | ||
+ | * Implementing interfaces | ||
+ | * Using traits | ||
+ | * Implementing any method other than '' | ||
+ | * Declaring the entire class '' | ||
===== Future Scope ===== | ===== Future Scope ===== | ||
Line 278: | Line 376: | ||
==== Arbitrary Expressions ==== | ==== Arbitrary Expressions ==== | ||
- | ===== Proposed Voting Choices ===== | + | **TODO** |
- | Include these so readers know where you are heading and can discuss the proposed voting options. | + | |
- | ===== Patches and Tests ===== | + | ==== Extension to Anonymous Functions |
- | Links to any external patches and tests go here. | + | |
- | If there is no patch, make it clear who will create a patch, or whether a volunteer to help with implementation is needed. | + | **TODO** |
- | Make it clear if the patch is intended to be the final patch, or is just a prototype. | + | ===== Proposed Voting Choices ===== |
- | For changes affecting the core language, you should also provide a patch for the language specification. | + | Add property capture to anonymous classes, with the syntax and semantics proposed, in PHP 8.3 (Yes / No, two-thirds majority required for acceptance) |
+ | |||
+ | ===== Patches and Tests ===== | ||
+ | |||
+ | **TODO** | ||
===== Implementation ===== | ===== Implementation ===== | ||
Line 301: | Line 401: | ||
===== Rejected Features ===== | ===== Rejected Features ===== | ||
- | Keep this updated with features that were discussed on the mail lists. | + |
rfc/property-capture.txt · Last modified: 2023/04/23 21:15 by imsop