Revisiting Anonymous Classes

From: Date: Sat, 28 Jun 2014 13:36:48 +0000
Subject: Revisiting Anonymous Classes
Groups: php.internals 
Request: Send a blank email to internals+get-75122@lists.php.net to get a copy of this message
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 [1]: "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. I was surprised to find [2] (and even more so because I voted "No" on it ... and had no recollection of reading the RFC or voting on it). Most likely I did not see a use case for anonymous classes back then. I would like to propose the following syntax for declaring an anonymous class that does not implement an interface or extend a class: $o = new { public function method() { // ... } // ... }; An anonymous class can extend one class or implement one interface. Unlike non-anonymous classes, an anonymous class cannot do both. In other words, it cannot both extend a class and implement an interface, nor can it implement more than one interface. The syntax to have an anonymous class implement an interface or extend a class is the same: interface AnInterface { public function method(); } $o = new AnInterface { public function method() { // ... } } class AClass { public function method() { // ... } } $o = new AClass { // ... } The ReflectionClass and ReflectionObject classes need to be adapted for anonymous classes. Only new syntax elements would be added to the PHP language. Existing elements of the PHP language syntax would not be changed. No new reserved words would be added to the PHP language. There should not be an impact on backwards compatibility. In case there is enough positive feedback to the syntax proposed in this email I would gladly write a formal RFC. I could also help with writing tests and documentation. Unfortunately I cannot implement the feature myself. -- [1] http://blog.8thlight.com/uncle-bob/2014/05/14/TheLittleMocker.html [2] https://wiki.php.net/rfc/anonymous_classes

« previous php.internals (#75122) next »