Unexpected behaviour when using Traits with final methods

From: Date: Wed, 14 Jun 2023 19:33:53 +0000
Subject: Unexpected behaviour when using Traits with final methods
Groups: php.internals 
Request: Send a blank email to internals+get-120576@lists.php.net to get a copy of this message
Hi all, I'm running into something which peaked my curiousity due to its unexpected behaviour, so I'm writing to the list in the hopes of finding out whether this is by design, a bug or an oversight which should be fixed (via an RFC?).
The precedence order is that members from the current class override Trait methods, which in turn override inherited methods.
Source: https://www.php.net/manual/en/language.oop5.traits.php#language.oop5.traits.precedence If one would want to prevent the "current class" from being able to override a trait method, I would expect that the final keyword would be able to do this, just like it would when a method is inherited from a parent class. Unfortunately, that does not seem to work and it appears that the current class can freely override final methods from a trait:
trait Foo {
    final protected function bar() {
        echo 'Foo';
    }
}

class FooBar {
    use Foo;

    public function __construct() {
        $this->bar();
    }

    protected function bar() {
        echo 'FooBar';
    }
}

new FooBar(); // Prints "FooBar".
https://3v4l.org/hlirb Which brings me to my second point: in PHP 8.0 the use of the final keyword with private methods has been turned into a warning via this RFC: https://wiki.php.net/rfc/inheritance_private_methods ... but the "current class" has access to private methods inherited from a trait, so I would expect final private methods in traits to be exempt from that warning, but turns out that that will still throw the warning: https://3v4l.org/Vb0S2 Is there anyone who can shed some light on this behaviour ? Smile, Juliette

« previous php.internals (#120576) next »