问题
I use PHP 7.1.0.
Let's say we have a trait, we use it inside a class and rename the imported method:
trait T
{
public function A() {
echo ".";
}
}
class C
{
use T {
A as B;
}
}
$c = new C();
$c->B();
$c->A(); // Why does it work?
Why does PHP still allow me to use old method name (A
in this case)?
It's really a pain because in more complex examples you cannot rely on method renaming - and thus you can unexpectedly receive "incompatible declarations" error:
class BaseSrc
{
}
trait BaseTrait
{
public function init(BaseSrc $baseSrc)
{
echo "Init Base";
}
}
class Base
{
use BaseTrait {
BaseTrait::init as initBase;
}
}
$base = new Base();
$base->initBase(new BaseSrc());
$base->init(new BaseSrc()); // WHY DOES IT WORK?????
class MainSrc extends BaseSrc
{
}
trait MainTrait
{
use BaseTrait {
BaseTrait::init as initBase;
}
public function init(MainSrc $mainSrc)
{
$this->initBase($mainSrc);
echo "Init Main";
}
}
// Warning: Declaration of MainTrait::init(MainSrc $mainSrc) should be compatible with Base::init(BaseSrc $baseSrc)
class Main extends Base
{
use MainTrait;
}
I think, this code should work. Since I renamed init()
into initBase()
in the Base
class AND did the same renaming when using BaseTrait
inside MainTrait
, I expect that this method (BaseTrait::init()
) will not conflict with MainTrait::init()
. In fact, PHP says that I have incompatible declarations. The reason behind it is that renaming init as initBase
does not work - method init
is still there, in my Base
class!
Is there any way how to solve this problem without renaming BaseTrait::init() into something like BaseTrait::initBase() from the very beginning (not just in the use
statement)?
Should I consider this as a PHP bug and report it? Is there anything reasonable behind this behaviour?
回答1:
As mentioned in the comments and for completeness; From the PHP manual section on Traits:
The
Aliased_Talker
makes use of the as operator to be able to use B'sbigTalk
implementation under an additional alias talk.
And then:
The as operator can be used to add an alias to one of the methods. Note the as operator does not rename the method and it does not affect any other method either.
So as
adds an alias but does not replace or affect the original method in any way. This is the expected behavior.
来源:https://stackoverflow.com/questions/43836171/why-method-renaming-does-not-work-in-php-traits