rfc:anonymous_classes

Differences

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

Link to this comparison view

Both sides previous revisionPrevious revision
Next revision
Previous revision
rfc:anonymous_classes [2015/03/13 19:26] – Initiated vote philsturfc:anonymous_classes [2017/09/22 13:28] (current) – external edit 127.0.0.1
Line 4: Line 4:
   * Date: 2013-09-22   * Date: 2013-09-22
   * Author: Joe Watkins <krakjoe@php.net>, Phil Sturgeon <philstu@php.net>   * Author: Joe Watkins <krakjoe@php.net>, Phil Sturgeon <philstu@php.net>
-  * Status: Voting+  * Status: Implemented (in PHP 7.0)
   * First Published at: http://wiki.php.net/rfc/anonymous_classes   * First Published at: http://wiki.php.net/rfc/anonymous_classes
  
Line 27: Line 27:
 }); });
 </code> </code>
 +
 +===== Syntax and Examples =====
 +
 +new class (arguments) {definition}
 +
 +Note: in a previous version of this RFC, the arguments were after the definition, this has been changed to reflect the feedback during the last discussion.
 +
 +<code php>
 +<?php
 +/* implementing an anonymous console object from your framework maybe */
 +(new class extends ConsoleProgram {
 +    public function main() {
 +       /* ... */
 +    }
 +})->bootstrap();
 +
 +/* return an anonymous implementation of a Page for your MVC framework */
 +return new class($controller) implements Page {
 +    public function __construct($controller) {
 +        /* ... */
 +    }
 +    /* ... */
 +};
 +
 +/* vs */
 +class MyPage implements Page {
 +    public function __construct($controller) {
 +        /* ... */
 +    }
 +    /* ... */
 +}
 +return new MyPage($controller);
 +
 +/* return an anonymous extension of the DirectoryIterator class */
 +return new class($path) extends DirectoryIterator {
 +   /* ... */
 +};
 +
 +/* vs */
 +class MyDirectoryIterator {
 +    /* .. */
 +}
 +return new MyDirectoryIterator($path);
 +
 +/* return an anon class from within another class (introduces the first kind of nested class in PHP) */
 +class MyObject extends MyStuff {
 +    public function getInterface() {
 +        return new class implements MyInterface {
 +            /* ... */
 +        };
 +    }
 +}
 +
 +
 +/* return a private object implementing an interface */
 +class MyObject extends MyStuff {
 +    /* suitable ctor */
 +    
 +    private function getInterface() {
 +        return new class(/* suitable ctor args */) extends MyObject implements MyInterface {
 +            /* ... */
 +        };
 +    }
 +}
 +</code>
 +
 +Note: the ability to declare and use a constructor in an anonymous class is necessary where control over construction must be exercised.
 +
 +===== Inheritance/Traits =====
 +
 +Extending classes works just as you'd expect.
 +
 +<code php>
 +<?php
 +
 +class Foo {}
 +
 +$child = new class extends Foo {};
 +
 +var_dump($child instanceof Foo); // true
 +</code>
 +
 +Traits work identically as in named class definitions too.
 +
 +<code php>
 +<?php
 +
 +trait Foo {
 +    public function someMethod() {
 +      return "bar";
 +    }
 +}
 +
 +$anonClass = new class {
 +    use Foo;
 +};
 +
 +var_dump($anonClass->someMethod()); // string(3) "bar"
 +</code>
 +
 +===== Reflection =====
 +
 +The only change to reflection is to add ReflectionClass::isAnonymous().
 +
 +===== Serialization =====
 +
 +Serialization is not supported, and will error just as anonymous functions do.
 +
 +===== Internal Class Naming =====
 +
 +The internal name of an anonymous class is generated with a unique reference based on its address.
 +
 +<code php>
 +function my_factory_function(){
 +    return new class{};
 +}
 +</code>
 +
 +get_class(my_factory_function()) would return "class@0x7fa77f271bd0" even if called multiple times, as it is the same definition. The word "class" is used by default, but if the anonymous class extends a named class it will use that:
 +
 +<code php>
 +class mine {}
 +
 +new class extends mine {};
 +</code>
 +
 +This class name will be "mine@0x7fc4be471000".
 +
 +Multiple anonymous classes created in the same position (say, a loop) can be compared with `==`, but those created elsewhere will not match as they will have a different name.
 +
 +<code php>
 +$identicalAnonClasses = [];
 +
 +for ($i = 0; $i < 2; $i++) {
 +    $identicalAnonClasses[$i] = new class(99) {
 +        public $i;
 +        public function __construct($i) {
 +            $this->i = $i;
 +        }
 +    };
 +}
 +
 +var_dump($identicalAnonClasses[0] == $identicalAnonClasses[1]); // true
 +
 +$identicalAnonClasses[2] = new class(99) {
 +    public $i;
 +    public function __construct($i) {
 +        $this->i = $i;
 +    }
 +};
 +
 +var_dump($identicalAnonClasses[0] == $identicalAnonClasses[2]); // false
 +</code>
 +
 +Both classes where identical in every way, other than their generated name.
  
 ===== Use Cases ===== ===== Use Cases =====
Line 65: Line 220:
 $subject->attach(new class implements SplObserver { $subject->attach(new class implements SplObserver {
   function update(SplSubject $s) {   function update(SplSubject $s) {
-    printf("Got update from: %s\n" $subject);+    printf("Got update from: %s\n"$subject);
   }   }
 }); });
Line 218: Line 373:
  
 The changes made by this patch mean named nested classes are easier to implement (by a tiny bit). The changes made by this patch mean named nested classes are easier to implement (by a tiny bit).
- 
-===== Proposed Voting Choices ===== 
- 
-Straight forward, we should have this, we should not have this. 
- 
-===== Syntax and Examples ===== 
- 
-new class (arguments) {definition} 
- 
-Note: in a previous version of this RFC, the arguments were after the definition, this has been changed to reflect the feedback during the last discussion. 
- 
-<code php> 
-<?php 
-/* implementing an anonymous console object from your framework maybe */ 
-(new class extends ConsoleProgram { 
-    public function main() { 
-       /* ... */ 
-    } 
-})->bootstrap(); 
- 
-/* return an anonymous implementation of a Page for your MVC framework */ 
-return new class($controller) implements Page { 
-    public function __construct($controller) { 
-        /* ... */ 
-    } 
-    /* ... */ 
-}; 
- 
-/* vs */ 
-class MyPage implements Page { 
-    public function __construct($controller) { 
-        /* ... */ 
-    } 
-    /* ... */ 
-} 
-return new MyPage($controller); 
- 
-/* return an anonymous extension of the DirectoryIterator class */ 
-return new class($path) extends DirectoryIterator { 
-   /* ... */ 
-}; 
- 
-/* vs */ 
-class MyDirectoryIterator { 
-    /* .. */ 
-} 
-return new MyDirectoryIterator($path); 
- 
-/* return an anon class from within another class (introduces the first kind of nested class in PHP) */ 
-class MyObject extends MyStuff { 
-    public function getInterface() { 
-        return new class implements MyInterface { 
-            /* ... */ 
-        }; 
-    } 
-} 
- 
- 
-/* return a private object implementing an interface */ 
-class MyObject extends MyStuff { 
-    /* suitable ctor */ 
-     
-    private function getInterface() { 
-        return new class(/* suitable ctor args */) extends MyObject implements MyInterface { 
-            /* ... */ 
-        }; 
-    } 
-} 
-</code> 
- 
-Note: the ability to declare and use a constructor in an anonymous class is necessary where control over construction must be exercised. 
- 
-===== Inheritance/Traits ===== 
- 
-Extending classes works just as you'd expect. 
- 
-<code php> 
-<?php 
- 
-class Foo {} 
- 
-$child = new class extends Foo {}; 
- 
-var_dump($child instanceof Foo); // true 
-</code> 
- 
-Traits work identically as in named class definitions too. 
- 
-<code php> 
-<?php 
- 
-trait Foo { 
-    public function someMethod() { 
-      return "bar"; 
-    } 
-} 
- 
-$anonClass = new class { 
-    use Foo; 
-}; 
- 
-var_dump($anonClass->someMethod()); // string(3) "bar" 
-</code> 
- 
-===== Reflection ===== 
- 
-The only change to reflection is to add ReflectionClass::isAnonymous(). 
- 
-===== Serialization ===== 
- 
-Serialization is not supported, and will error just as anonymous functions do. 
- 
-===== Code Paths ===== 
- 
-Code such as: 
- 
-<code php> 
-while ($i++<10) { 
-    class myNamedClass { 
-        /* ... */ 
-    } 
-} 
-</code> 
- 
-will fail to execute, however code such as: 
- 
-<code php> 
-while ($i++<10) { 
-  new class {}; 
-} 
-</code> 
- 
-will work as expected: the definition will be re-used, creating a new object. 
- 
-===== Internal Class Naming ===== 
- 
-The internal name of an anonymous class is generated with a unique reference based on its address. 
- 
-<code php> 
-function my_factory_function(){ 
-    return new class{}; 
-} 
-</code> 
- 
-get_class(my_factory_function()) would return "class@0x7fa77f271bd0" even if called multiple times, as it is the same definition. The word "class" is used by default, but if the anonymous class extends a named class it will use that: 
- 
-<code php> 
-class mine {} 
- 
-new class extends mine {}; 
-</code> 
- 
-This class name will be "mine@0x7fc4be471000". 
- 
-Multiple anonymous classes created in the same position (say, a loop) can be compared with `==`, but those created elsewhere will not match as they will have a different name. 
- 
-<code php> 
-$identicalAnonClasses = []; 
- 
-for ($i = 0; $i < 2; $i++) { 
-    $identicalAnonClasses[$i] = new class(99) { 
-        public $i; 
-        public function __construct($i) { 
-            $this->i = $i; 
-        } 
-    }; 
-} 
- 
-var_dump($identicalAnonClasses[0] == $identicalAnonClasses[1]); // true 
- 
-$identicalAnonClasses[2] = new class(99) { 
-    public $i; 
-    public function __construct($i) { 
-        $this->i = $i; 
-    } 
-}; 
- 
-var_dump($identicalAnonClasses[0] == $identicalAnonClasses[2]); // false 
-</code> 
- 
-Both classes where identical in every way, other than their generated name. 
- 
- 
-===== Implementation ===== 
- 
-https://github.com/php/php-src/pull/1118 
  
 ===== References ===== ===== References =====
Line 409: Line 378:
 PHP 7 Discussion: http://marc.info/?l=php-internals&m=142478600309800&w=2 PHP 7 Discussion: http://marc.info/?l=php-internals&m=142478600309800&w=2
  
-===== Vote =====+===== Proposed Voting Choices =====
  
 The voting choices are yes (in favor for accepting this RFC for PHP 7) or no (against it). The voting choices are yes (in favor for accepting this RFC for PHP 7) or no (against it).
  
-This RFC requires a 2/3 majority.+===== Vote =====
  
 Vote starts on March 13th, and will end two weeks later, on March 27th. Vote starts on March 13th, and will end two weeks later, on March 27th.
  
-<doodle title="Anonymous Classes" auth="philstu" voteType="single" closed="false">+This RFC requires a 2/3 majority. 
 + 
 +<doodle title="Anonymous Classes" auth="philstu" voteType="single" closed="true">
    * Yes    * Yes
    * No    * No
Line 431: Line 402:
   * v0.3: ReflectionClass::isAnonymous() and simple example   * v0.3: ReflectionClass::isAnonymous() and simple example
   * v0.2: Brought back for discussion   * v0.2: Brought back for discussion
-  * v0.1: Initial draftsn+  * v0.1: Initial draft 
 + 
 +===== Implementation ===== 
 + 
 +https://github.com/php/php-src/pull/1118
rfc/anonymous_classes.1426274787.txt.gz · Last modified: 2017/09/22 13:28 (external edit)