PHP覆盖父类trait的方法

8
我正在使用Laravel 5.1,但这并不特定于该框架,这更是一个通用的PHP问题。
有一个指定了trait的父类:
namespace Illuminate\Foundation\Auth;

use Illuminate\Auth\Authenticatable;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Auth\Passwords\CanResetPassword;
use Illuminate\Foundation\Auth\Access\Authorizable;
use Illuminate\Contracts\Auth\Authenticatable as AuthenticatableContract;
use Illuminate\Contracts\Auth\Access\Authorizable as AuthorizableContract;
use Illuminate\Contracts\Auth\CanResetPassword as CanResetPasswordContract;

class User extends Model implements
  AuthenticatableContract,
  AuthorizableContract,
  CanResetPasswordContract {
    use Authenticatable, Authorizable, CanResetPassword;
}

然后我有一个用户类,我关心它是否从那个类继承:
namespace App\Api\V1\Models;

use Illuminate\Foundation\Auth\User as Authenticatable;
use Zizaco\Entrust\Traits\EntrustUserTrait;

class User extends Authenticatable {
  use EntrustUserTrait {
    EntrustUserTrait::can insteadof \Illuminate\Foundation\Auth\Access\Authorizable;
  }
}

“EntrustUserTrait”具有一个与“Authorizable”trait冲突的“can()”方法。然而,“Authorizable” trait位于父类中,因此会抛出错误“Required Trait wasn't added to App\Api\V1\Models\User”。我已经搜索了很多信息,关于在子类中覆盖声明的traits有很多信息,但我似乎找不到关于如何覆盖父类中的traits的任何信息。”

你根本不需要使用 insteadof。can 会覆盖父级的 can - apokryfos
除了它并没有这样做,它会抛出一个关于未应用特质的错误,因为它与另一个特质冲突。我认为这是一些边缘情况,因为下面的示例确实可以工作并覆盖其他特质。但我不确定区别在哪里。 - jdforsythe
1个回答

5
请看下面的代码:

考虑以下代码:

<?php    
trait AA {
    function f() { 
        echo "I'm AA::f".PHP_EOL;
    }
}
class A {
    use AA;
}
trait BB {
    function f() { 
        echo "I'm BB::f".PHP_EOL;
    }
}
class B extends A {
    use BB;
}
$b = new B();    
$b->f();

我是BB::f

我认为特质就像复制粘贴的代码。在使用特质的类中,特质代码被视为“复制粘贴”的代码,因此您可以假装特质并没有真正被继承,而它的代码只是父类的一部分。


确实,你的例子是可以工作的。也许与我的情况不同的是,父类实现了一个需要它实现该方法的接口?或者接口定义了不同的函数签名?我不确定。但我决定创建一个单独的类来实现合同并添加特性,而不是扩展父类,因为它只是实现合同并添加特性。 - jdforsythe
如果是这种情况,不同的方法签名确实会导致冲突。 - apokryfos

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接