rfc:anonymous_classes_v2

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_v2 [2014/10/22 07:02] krakjoerfc:anonymous_classes_v2 [2017/09/22 13:28] (current) – external edit 127.0.0.1
Line 9: Line 9:
 We have looked at anonymous classes before http://wiki.php.net/rfc/anonymous_classes We have looked at anonymous classes before http://wiki.php.net/rfc/anonymous_classes
  
-The patch is only a tiny bit different, moving constructor arguments to the position where most expect them.+There has been many requests from the community to incorporate this feature, most recently here: http://grokbase.com/t/php/php-internals/146wpa11s5/revisiting-anonymous-classes from Sebastian Bergmann, author of PHPUnit.
  
-Many many use cases were put forward by the community for the last RFC and they all still apply.+Follows is an edited version of that communication, based on the proposed patch.
  
 ===== Proposal ===== ===== Proposal =====
  
-Some example code ...+In a unit test, test doubles (dummies, fakes, stubs, spys, and mocks) are used to simulate the behavior of complex, real objects when a real object is difficult or impossible to incorporate into a unit test. A test double can be used anywhere in the program where the program expects an object of the original class. 
 + 
 +Traditionally, frameworks and libraries are used to automatically generate test double objects based on the original objects using reflection. This idea stems from a time when IDEs were not powerful enough to do this generation for us. 
 + 
 +Quoting Robert C. Martin: 
 + 
 +    Stubs and spies are very easy to write. My IDE makes it trivial. 
 +    I just point at the interface and tell the IDE to implement it. 
 +    Voila! It gives me a dummy. Then I just make a simple modification 
 +    and turn it into a stub or a spy. [...] 
 +    I don't like the strange syntax of mocking tools, and the 
 +    complications they add to my setups. I find writing my own test 
 +    doubles to be simpler in most cases. 
 + 
 +The more I think about this (especially in the aftermath of the unserialize() issue), the more it appeals to me to have "real code", generated in parts by my IDE, for my test doubles. 
 + 
 +The question remains, though, where to put this code. Obviously it belongs with the test suite. But how to name the test double classes? Unique names are required to be able to have multiple (differently configured) test doubles for the same original class. Mocking tools (such as PHPUnit_MockObject, for instance) use random names for their test double classes. 
 + 
 +Anonymous classes could be a solution for this problem. 
 + 
 +This RFC proposes the following syntax for creating an object of an anonymous class, where the class does not extend from another and implements no interfaces.
  
 <code php> <code php>
-<?php +$test = new class("Hello World"{ 
-class {}+    public function __construct($greeting) { 
 +        $this->greeting = $greeting; 
 +    } 
 +}; 
 +</code>
  
-trait ArrayAccessor { +The normal rules of inheritance apply to anonymous classesan anonymous class that inherits a parent would be declared as follows: 
-    public function offsetSet($offset$data) { return $this->{$this->name}[$offset] = $data; } + 
-    public function offsetGet($offset)        { return $this->{$this->name}[$offset]; } +<code php
-    public function offsetUnset($offset)      { return $this->{$this->name}[$offset]; } +<?php 
-    public function offsetExists($offset)     { return isset($this->{$this->name}[$offset]); } +$test = new class("Hello World"
-     +            extends AnotherClass { 
-    public function setArray($name, $member) { +    public function __construct($greeting) { 
-        $this->name = $name; +        $this->greeting = $greeting;
-        $this-> +
-            {$this->name} = $member;+
     }     }
-     +}; 
-    private $name;+</code> 
 + 
 +An anonymous class, as any other class, can implement many interfaces as follows: 
 + 
 +<code php> 
 +<?php 
 +interface SomeInterface { 
 +    public function method();
 } }
  
 +$test = new class("Hello World")
 +            extends AnotherClass implements SomeInterface {
 +    public function __construct($greeting) {
 +        $this->greeting = $greeting;
 +    }
 +
 +    /* implement SomeInterface */
 +    public function method() {}
 +};
 +</code>
 +
 +An anonymous class may also use traits, in the normal way:
 +
 +<code php>
 +<?php
 $test = new class(["hello", "world"]) $test = new class(["hello", "world"])
-            extends A implements ArrayAccess {+            implements ArrayAccess { 
 +    /* assume this trait implements ArrayAccess and contains ::setArray */
     use ArrayAccessor;     use ArrayAccessor;
          
Line 46: Line 91:
     protected $data;     protected $data;
 }; };
- 
-var_dump($test, 
-         $test instanceof ArrayAccess, 
-         $test instanceof A, 
-         class_uses($test), 
-         $test[0], $test[1]); 
 ?> ?>
 </code> </code>
  
-Detail how anonymous classes can be used to make better use of traits here ... +The ReflectionClass has been updated with ReflectionClass::isAnonymous()
- +
-Detail other things here ...+
  
 ===== Proposed PHP Version(s) ===== ===== Proposed PHP Version(s) =====
rfc/anonymous_classes_v2.1413961364.txt.gz · Last modified: 2017/09/22 13:28 (external edit)