Alias method from Trait in Parent Class

Viewed 1835

I'm wondering if this is possible in PHP:

trait SomeTrait
{
    public function someMethod() { /* ... */ }
}

class Parent
{
    use SomeTrait;
}

class Child extends Parent
{
    /* Do something to rename someMethod() to someOtherMethod() */
    use someMethod as someOtherMethod; // Example

    public function someMethod()
    {
        // Do something different than SomeTrait::someMethod()
    }
}

In my actual use-case, the Parent class is a parent to several children (and none of them actually use the someMethod() that comes from the trait applied to the parent class. The Parent class is also part of an external library, so I cannot directly modify the source code.

The Child class in my actual use-case also relies on protected properties from the Parent class, so I'm fairly certain that I need to keep the inheritance.

Is this actually possible, or do I just need to deal with it, and use a different method name on the Child class in question?

2 Answers

What you've got in the question should work fine if you just want to override it. As per the manual:

The precedence order is that members from the current class override Trait methods, which in turn override inherited methods.

If you need to provide an alias in the child class, then you can re-use the trait in the child class, making use of the as operator to define an alias in the current class:

class Child extends Foo
{
  // This will re-import the trait into your child class, aliasing
  // any specified methods.
  use SomeTrait {
    someMethod as someOtherMethod;
  }

  public function someMethod() {
    $this->someOtherMethod();
  }
}

You can also control the visibility of the new alias, e.g.

use SomeTrait {
  someMethod as private someOtherMethod;
}

All that said, I don't really see the benefit of this, when you could just call

parent::someMethod();

after over-riding it. But it might be useful if you've got a particularly complex inheritance tree.

Full example here: https://eval.in/868453

I literally tested this yesterday with the following code :-)

<?php

trait CanWhatever
{
    public function doStuff()
    {
        return 'result!';
    }
}

class X
{
    use CanWhatever;

    public function doStuff()
    {
        return 'overridden!';
    }
}

$x = new X();
echo $x->doStuff();
echo "\n\$x has ";
echo (class_uses($x, 'CanWhatever')) ? 'the trait' : 'no trait';

The output was:

overridden! 
$x has the trait

So keeping the name the same just overrides as per normal.

Check it out here https://3v4l.org/Vin2H

Related