# RFC: Final class constants

- Status: Implemented (PHP 8.1)
- Authors: Máté Kocsis kocsismate@php.net
- Date: 2021-04-23
- Target: PHP 8.1
- Implementation: https://github.com/php/php-src/pull/6878
- Original: https://wiki.php.net/rfc/final_class_const
- Page: https://externals.io/rfc/final_class_const
- More for agents: search with https://externals.io/search.md?q={query} · RFCs at https://externals.io/rfc.md · JSON API at https://externals.io/api · documentation at https://externals.io/llms.txt

## Votes

### Add support for final class constants? (closed)

Yes: 29 · No: 4

Voters: alec (Yes), asgrim (Yes), ashnazg (Yes), bmajdak (Yes), brzuchal (Yes), bwoebi (Yes), crell (Yes), derick (Yes), galvao (Yes), gasolwu (Yes), geekcom (Yes), girgias (No), irker (Yes), jbnahan (Yes), jhdxr (No), kalle (Yes), kguest (Yes), kocsismate (Yes), lcobucci (Yes), levim (No), mbeccati (Yes), mgocobachi (Yes), nicolasgrekas (Yes), ocramius (Yes), reywob (No), sebastian (Yes), sergey (Yes), svpernova09 (Yes), tandre (Yes), theodorejb (Yes), twosee (Yes), weierophinney (Yes), wyrihaximus (Yes)

## Discussions on the mailing list

- [\[RFC\] \[Discussion\] Final constants](https://externals.io/message/114273.md) — started on 2021-05-04, 4 messages
- [\[RFC\] \[Vote\] Final constants](https://externals.io/message/114522.md) — started on 2021-05-19, 4 messages
- [\[RFC\] \[Initial Feedback\] Abstract class constants](https://externals.io/message/132228.md) — started on 2026-08-15, 1 messages

---

## Introduction

Currently, class constants are always overridable by child classes. This causes a few smaller caveats:

First of all, the engine can't optimize class constant references when late static binding is involved, so it has to pessimistically assume that `FOO` is overridden in case of `static::FOO` or `$this::FOO` invocations.

What's more important is that class constants are not guaranteed to stay constant. Even if the declaring class always references them by using `self::`, doing so won't prevent a child class from changing their value or even their type, unless the parent is a final class. Although constants not being constants is usually considered only as a theoretical problem, being able to add a `final` modifier would make the intention explicit that child classes shouldn't try to override them (e.g. because the parent doesn't use late static binding).

A related interesting fact is that interface constants are already `final`:

```php
interface I
{
    public const X = "i";
}
 
class C implements I
{
    public const X = "bar";
}
 
// Fatal error: Cannot inherit previously-inherited or override constant X from interface I
```

This leads to a weird inconsistency. By introducing an intermediate class, overriding still becomes possible:

```php
interface I
{
    public const X = "i";
}
 
class C implements I
{
}
 
class D extends C 
{
    public const X = "d";
}
 
// No error
```

## Proposal

The final modifier can be added to class constants. Doing so prevents overriding of a constant:

```php
class Foo
{
    final public const X = "foo";
}
 
class Bar extends Foo
{
    public const X = "bar";
}
 
// Fatal error: Bar::X cannot override final constant Foo::X
```

Besides, interface constants would become overridable by default, and the `final` modifier could be used to retain the original behavior.

```php
interface I
{
    public const X = "i";
    final public const Y = "i";
}
 
class C implements I
{
    public const X = "c"; // Overriding I::X is possible
    public const Y = "c"; // Overriding I::Y is not possible
}
 
// Fatal error: C::Y cannot override final constant I::Y
```

## Reflection

A `ReflectionClassConstant::isFinal()` method is added in order to be able to retrieve if a constant is final.

## Backward Incompatible Changes

None.

## Vote

Voting started on 2021-05-19 08:00 UTC and ends 2021-06-02 08:00 UTC. The vote requires 2/3 majority to be accepted.

**Vote: Add support for final class constants?** — Yes: 29 · No: 4 (closed)
