Final by default anonymous classes View as Markdown

Declined
Authors
Daniil Gentili daniil@daniil.it
Date
2023-12-23
Source
wiki.php.net/rfc/final_by_default_anonymous_classes

Votes

Make final anonymous classes final by default? closed
Yes
21
No
14
35 voters
alcaeus No 2024-01-17 08:33
alec No 2024-01-16 06:59
ashnazg Yes 2024-01-17 15:14
brzuchal No 2024-01-15 11:49
bukka No 2024-01-15 10:57
crell Yes 2024-01-16 22:32
derick Yes 2024-01-17 08:41
devnexen No 2024-01-15 14:43
dharman No 2024-01-16 21:55
fabpot No 2024-01-29 16:23
girgias Yes 2024-01-17 15:10
ilutov Yes 2024-01-15 12:54
josh Yes 2024-01-15 18:56
kalle No 2024-01-15 11:05
kguest Yes 2024-01-22 14:33
kocsismate Yes 2024-01-15 19:41
marandall Yes 2024-01-16 22:04
mbeccati No 2024-01-22 07:56
narf No 2024-01-15 12:42
nicolasgrekas No 2024-01-15 10:57
nikic Yes 2024-01-15 11:09
ocramius Yes 2024-01-15 16:57
pierrick Yes 2024-01-16 21:59
saki No 2024-01-15 15:21
santiagolizardo Yes 2024-01-20 13:19
seld No 2024-01-29 21:35
sergey Yes 2024-01-16 21:49
stas Yes 2024-01-17 00:42
svpernova09 Yes 2024-01-22 15:30
theodorejb Yes 2024-01-28 03:58
thorstenr Yes 2024-01-29 10:00
timwolla Yes 2024-01-15 14:43
trowski Yes 2024-01-16 21:41
villfa No 2024-01-18 08:45
weierophinney Yes 2024-01-17 00:15
Add an optional open keyword for anonymous classes? closed
Yes
0
No
30
30 voters
alcaeus No 2024-01-17 08:33
ashnazg No 2024-01-17 15:14
brzuchal No 2024-01-15 11:48
bukka No 2024-01-15 10:57
crell No 2024-01-16 22:32
devnexen No 2024-01-15 14:43
dharman No 2024-01-16 21:55
fabpot No 2024-01-29 16:23
girgias No 2024-01-17 15:09
ilutov No 2024-01-15 12:54
kalle No 2024-01-15 11:06
kguest No 2024-01-22 14:33
kocsismate No 2024-01-15 19:41
marandall No 2024-01-16 22:04
narf No 2024-01-15 12:42
nicolasgrekas No 2024-01-15 10:57
nikic No 2024-01-15 11:09
ocramius No 2024-01-15 16:57
pierrick No 2024-01-16 21:59
saki No 2024-01-15 15:22
santiagolizardo No 2024-01-20 13:19
sebastian No 2024-01-15 11:44
sergey No 2024-01-15 14:47
svpernova09 No 2024-01-22 15:30
theodorejb No 2024-01-15 14:10
thorstenr No 2024-01-29 09:59
timwolla No 2024-01-15 13:38
trowski No 2024-01-16 21:41
villfa No 2024-01-18 08:45
weierophinney No 2024-01-17 00:16

Discussions on the mailing list

Final anonymous classes
by Daniil Gentili · 10 messages
[RFC] [Discussion] Final anonymous classes
by Daniil Gentili · 6 messages
[VOTE] [RFC] Final anonymous classes
by Daniil Gentili · 10 messages
[RFC] [Discussion] Final by default anonymous classes
by Daniil Gentili · 1 message
[VOTE] [RFC] Final-by-default anonymous classes
by Daniil Gentili · 8 messages

RFC text

Copied from wiki.php.net, last synchronized Oct 13, 2026 11:52 UTC

Introduction

This RFC proposes to make anonymous classes final by default.

Proposal

This RFC proposes to make anonymous classes final by default.

The main reason for this change, in my view, is to allow some additional opcache optimizations, such as any JIT logic gated behind a check on ZEND_ACC_FINAL, i.e. https://github.com/php/php-src/blob/master/ext/opcache/jit/zend_jit_trace.c#L4507.

Another reason is mentioned by Nikita in https://externals.io/message/121906#121909: “It makes very little sense to me that everyone needs to explicitly mark their anonymous classes as final just because there is a class_alias loophole that could, in theory, have been used to extend anonymous classes in the past”.

Example, extending an anonymous class throws an error:

$x = new class {};
class_alias($x::class, 'alias');
class aliasExtends extends alias {}

'' Fatal error: Class aliasExtends cannot extend final class class@anonymous in %s on line %d ''

Optionally, an open keyword inspired by Kotlin can be introduced to optionally make anonymous classes non-final.

Example, extending an open anonymous class does not throw an error:

$x = new open class {};
class_alias($x::class, 'alias');
class aliasExtends extends alias {}

Rationale regarding open:

On one hand, looking at code like new class {}, you would assume that since the class apparently has no name, it should not be impossible to extend it, but on the other hand, there are valid usecases for extending even anonymous classes (comments in the PR (https://github.com/php/php-src/pull/11126 referenced proxying), and I can also think of phpunit mocking: completely precluding the possibility of mocking a class that

  1. Has a name (even if it's not immediately obvious)
  2. Can be referenced to using its name (class_exists, new ReflectionClass, new $clazz, and yes, even class_alias)

seems a tad bit too restrictive...

On the other hand, I also really don't like non-final classes, in all of my projects, I use CS rules that force all classes to either be abstract or final, because unfortunately, I've had to work with a lot of code that very frequently violates encapsulation by using inheritance.

Still, there are some useful patterns, mainly regarding testing and mocking, for example I use https://github.com/dg/bypass-finals as a dev dependency to make all final classes non-final at runtime to allow mocking in phpunit, but it works by installing a custom default stream contexts that intercepts requires, tokenizes files and removes final keywords from classes; this approach would break for anonymous classes if they were rendered final by default without an option to make them non-final.

Thus, I also propose the additional of an optional open keyword that can be used to make anonymous classes non-final.

The implementation PR will be provided by me in case of acceptance.

Backward Incompatible Changes

Anonymous classes will be rendered final by default.

Proposed PHP Version(s)

Next PHP 8.4

RFC Impact

See Backward Incompatible Changes.

Proposed Voting Choices

Voting started on January 15th, 2024 and runs until January 30th, 2024, 00:00 UTC.

2/3 required to accept.

Vote: Make final anonymous classes final by default? — Yes: 21 · No: 14 (closed)

2/3 required to accept.

Vote: Add an optional open keyword for anonymous classes? — Yes: 0 · No: 30 (closed)

References