Get "PHP 8 in a Nuthshell" (Now with PHP 8.4)
Amit Merchant

Amit Merchant

A blog on PHP, JavaScript, and more

Explicitly marking subclass methods as "overrides" in PHP 8.3

The #[\Override] attribute is a new attribute that will be introduced in PHP 8.3. It will be used to mark a method as overriding a parent method.

Before we get into the details of the #[\Override] attribute, let’s first understand the problem it’s trying to solve.

The problem

Essentially, when a class extends another class, it can override the methods of the parent class.

Check this simple example.

class ParentClass 
{
    public function foo(int $a, string $b) 
    {
        return "Parent";
    }
}

class ChildClass extends ParentClass 
{
    public function foo(int $a, string $b) 
    {
        return "Child";
    }
}

$child = new ChildClass();

$child->foo(1, "2");
// Child

As you can tell, here, the foo() method of the ChildClass is overriding the foo() method of the ParentClass. And when a child class is overriding a method of the parent class, it is important to make sure that the child class method has the same signature as the parent class method.

So, if we change the signature of the foo() method of the ChildClass to something like this,

class ChildClass extends ParentClass 
{
    public function foo(int $a) 
    {
        return "Child";
    }
}

Then, it will result in a fatal error that says the declaration of the child class method is not compatible with the parent class method.

PHP Fatal error:  Declaration of ChildClass::foo(int $a) 
must be compatible with ParentClass::foo(int $a, string $b) 
in /workspace/index.php on line 13

This is how PHP makes sure that the child class method is overriding the parent class method. That’s fair enough.

But there isn’t a way to check this in reverse.

Meaning, if the child class is overriding the parent class method and the signature of the method in the parent class changes, then there is no way to verify if the child class method is overriding any method of the parent class or not.

This is where the #[\Override] attribute comes into the picture.

The #[\Override] attribute

The #[\Override] attribute can be used to mark a method as overriding a parent method. And if the method is not overriding the method of the same name or signature of the parent class, then it will result in a compile-time error.

💡 Fun fact: Java has a similar @Override annotation which is used to mark a method as overriding a parent method. And it works in the same way as the #[\Override] attribute.

So, we can add the #[\Override] attribute to the foo() method of the ChildClass like this in our previous example.

class ChildClass extends ParentClass 
{
    #[\Override]
    public function foo(int $a, string $b) 
    {
        return "Child";
    }
}

Now, if the signature of the foo() method of the ParentClass changes, then it will result in a compile-time error.

class ParentClass 
{
    public function foo(int $a) 
    {
        return "Parent";
    }
}

The error would look something like this.

Fatal error: ChildClass::foo() has #[\Override] attribute, 
but no matching parent method exists

The same goes when a class is implementing an interface and marking a method as overriding a method of the interface.

interface Foo 
{
    public function foo(int $a, string $b);
}

class Bar implements Foo 
{
    #[\Override]
    public function foo(int $a, string $b) 
    {
        return "Bar";
    }
}

Here are all the rules for using the #[\Override] attribute.

  • Public and protected methods of a parent class or implemented interface satisfy #[\Override].
    • Abstract methods satisfy #[\Override].
    • Static methods behave as instance methods.
  • Private methods of a parent class do not satisfy #[\Override], because they are not part of the externally visible API.
  • __construct() of a parent class does not satisfy #[\Override], because it’s not part of the API of an already-constructed object.
  • The attribute is ignored on traits, but:
    • Abstract methods in a used trait satisfy #[\Override].
    • Regular methods in a used trait that are “shadowed” by a method in the class using the trait do not satisfy #[\Override].
    • Methods from a used trait behave as if the method definition was copied and pasted into the target class. Specifically the #[\Override] attribute on a trait method requires the existence of a matching method in a parent class or implemented interface.
  • #[\Override] works as expected on enums and anonymous classes.
  • #[\Override] works as expected on an interface. A matching method needs to exist in a parent interface.
Learn the fundamentals of PHP 8 (including 8.1, 8.2, 8.3, and 8.4), the latest version of PHP, and how to use it today with my new book PHP 8 in a Nutshell. It's a no-fluff and easy-to-digest guide to the latest features and nitty-gritty details of PHP 8. So, if you're looking for a quick and easy way to PHP 8, this is the book for you.

Like this article?

Buy me a coffee

👋 Hi there! I'm Amit. I write articles about all things web development. You can become a sponsor on my blog to help me continue my writing journey and get your brand in front of thousands of eyes.

Comments?