# Unexpected behaviour when using Traits with final methods

- Thread: https://externals.io/message/120576
- Original archive: https://news-web.php.net/php.internals/120576
- Started by Juliette Reinders Folmer on 2023-06-14T19:33:53+00:00
- Messages: 2
- RFC: Remove inappropriate inheritance signature checks on private methods (Implemented (PHP 8.0)) — https://externals.io/rfc/inheritance_private_methods.md
- Reply by email to internals@lists.php.net
- 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

---

## #120576 — Juliette Reinders Folmer — 2023-06-14T19:33:53+00:00

URL: https://externals.io/message/120576#120576

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

---

## #120579 — Erick de Azevedo Lima — 2023-06-14T22:20:04+00:00

URL: https://externals.io/message/120576#120579 · In reply to: #120576

Hi.

The point is: traits are not inheritance. It's assisted copy-and-paste.
When you use a trait, it's like you typed those methods yourself.
But if you type them in the class that's using the trait,
you throw away the method definition from the trait and use the one from
the class.
You can see here what the final keyword on your trait is intended for:

https://3v4l.org/loOqQ#v8.2.7

I hope I was able to help.

Best regards,
Erick

Em qua., 14 de jun. de 2023 às 16:34, Juliette Reinders Folmer <
php-internals_nospam@adviesenzo.nl> escreveu:

> 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?).
>
> > […]
> 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
