2016-04-05 55 views
5

我使用Laravel 5.1,但這不是特定於該框架,它更多的是一般的PHP問題。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; 
} 

然後,我有User類我很擔心從延長:

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; 
    } 
} 

EntrustUserTraitcan()方法與衝突Authorizable特質。但是,Authorizable特徵位於父類中,因此會引發錯誤Required Trait wasn't added to App\Api\V1\Models\User

我周圍搜索了很多關於在子類中聲明的重寫特徵的信息,但我似乎無法從父類中找到任何有關重寫特徵的信息。

+0

根本不需要做任何改變。 'can'會覆蓋父母的'can'。 – apokryfos

+0

除了沒有,它會拋出關於不應用特徵的錯誤,因爲它與另一個特徵發生衝突。不過,我認爲這是一些邊緣情況,因爲下面的例子確實有效並且覆蓋了其他特徵。雖然我不確定它們有什麼不同。 – jdforsythe

回答

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

我相信性狀工作就像複製粘貼代碼。特性代碼被視爲類中的「複製粘貼」代碼,因此您可以假裝該特性並非真正被繼承,但它的代碼只是父類的一部分。

+0

確實你的例子有效。也許與我的情況之間的區別是,父類實現了一個接口,要求它實現該方法?或者,也許界面正在定義不同的功能簽名?我不確定。但我只是決定創建一個單獨的類而不是擴展父項,因爲它所做的只是實現合同並添加特徵。 – jdforsythe

+0

如果是這種情況,不同的方法簽名確實會導致衝突。 – apokryfos