proper anonymous classes?

php.internals

Rasmus Schultz

7 years ago
The fact that the anonymous class syntax defines a class *and* immediately constructs an instance is quite annoying. For one, this is quite incompatible with DI containers' ability to resolve constructor arguments. Lets say you DI container can register a named component by merely referencing a class that uses constructor injection - so lets say this works: class MyController { public function __construct(MyService $service) { // ... } } $container->register("my-controller", MyController::class); Now I want to register an anonymous class, for example as part of an integration test-suite, which is common enough: $container->register("my-controller", new class { public function __construct(MyService $service) { // ... } }); This doesn't work, because you're expected to actually pass the constructor arguments immediately - because you can only define an anonymous class while immediately creating an instance. What I really want is just an anonymous class - not an instance, so: $container->register("my-controller", class { public function __construct(MyService $service) { // ... } }); The question is, what would a class expression without the new keyword evaluate to? Since we normally reference classes with just a class-name, I guess I'd expect a string, like you'd get from the ::class constant. Any hope for something like that?

Joe Watkins

7 years ago
What you describe is first class support for classes, nothing much to do with anonymous classes. On Wed, 13 Feb 2019, 09:01 Rasmus Schultz <rasmus@mindplay.dk wrote:

Rasmus Schultz

7 years ago
It doesn't have to be? It could just be an inline class expression (without the new keyword) that evaluates to a string, e.g. a machine-generated class-name? I don't think that's what first-class support means? e.g. nothing like constructors in JS or class instances like Dart? This could just be a "cheap hack" with machine-generated class-names, so we can reference anonymous classes by name, the same way we reference classes now. Introducing classes as instances of some kind of "class class" would be a more drastic change, since this would not be compatible with existing string type-hints for class-names. (?) On Wed, Feb 13, 2019 at 9:16 AM Joe Watkins <krakjoe@gmail.com> wrote:

Christoph Becker

7 years ago
On 13.02.2019 at 09:01, Rasmus Schultz wrote:
> The fact that the anonymous class syntax defines a class *and* immediately > constructs an instance is quite annoying. > > For one, this is quite incompatible with DI containers' ability to resolve > constructor arguments. > > Lets say you DI container can register a named component by merely > referencing a class that uses constructor injection - so lets say this > works: > > class MyController { > public function __construct(MyService $service) { > // ... > } > } > > $container->register("my-controller", MyController::class); > > Now I want to register an anonymous class, for example as part of an > integration test-suite, which is common enough: > > $container->register("my-controller", new class { > public function __construct(MyService $service) { > // ... > } > }); > > This doesn't work, because you're expected to actually pass the constructor > arguments immediately - because you can only define an anonymous class > while immediately creating an instance. > > What I really want is just an anonymous class - not an instance, so: > > $container->register("my-controller", class { > public function __construct(MyService $service) { > // ... > } > }); > > The question is, what would a class expression without the new keyword > evaluate to? > > Since we normally reference classes with just a class-name, I guess I'd > expect a string, like you'd get from the ::class constant. > > Any hope for something like that?
Not particularly efficient, but likely sufficient for the use case: $container->register("my-controller", get_class(new class { public function __construct(MyService $service) { // ... } }));
-- Christoph M. Becker