为何Laravel中类继承并实现接口未重写抽象方法?
问题:Laravel中实现接口却未重写方法的原因
我了解在PHP里,类继承父类时必须重写所有抽象方法,也可以重写非抽象方法;类实现接口时必须重写接口的所有方法。但在某个Laravel项目里发现例外:子类User继承Authenticatable类并实现MustVerifyEmail接口,却没重写接口里的抽象方法,代码如下:
父接口MustVerifyEmail
<?php interface MustVerifyEmail { /** * Determine if the user has verified their email address. * * @return bool */ public function hasVerifiedEmail(); /** * Mark the given user's email as verified. * * @return bool */ public function markEmailAsVerified(); /** * Send the email verification notification. * * @return void */ public function sendEmailVerificationNotification(); /** * Get the email address that should be used for verification. * * @return string */ public function getEmailForVerification(); }
参考父类示例
<?php class User extends Model implements AuthenticatableContract, AuthorizableContract, CanResetPasswordContract { use Authenticatable, Authorizable, CanResetPassword, MustVerifyEmail; }
子类User
<?php use Illuminate\Contracts\Auth\MustVerifyEmail; use Illuminate\Foundation\Auth\User as Authenticatable; class User extends Authenticatable implements MustVerifyEmail { /** * The attributes that are mass assignable. * * @var array<int, string> */ protected $fillable = [ 'name', 'email', 'password', ]; /** * The attributes that should be hidden for serialization. * * @var array<int, string> */ protected $hidden = [ 'password', ]; /** * The attributes that should be cast. * * @var array<string, string> */ protected $casts = [ 'email_verified_at' => 'datetime', 'password' => 'hashed', ]; public function activeCode() { return //... } public function hasTwoFactor($key) { return //... } public function isTwoFactorAuthEnabled() { return //... } }
解答
这是因为Laravel提供了一个同名的Trait MustVerifyEmail,它已经实现了MustVerifyEmail接口中定义的所有方法。
你看到的User类继承的Authenticatable类,或者参考示例里的User类本身,已经引入了这个Trait。Trait中的方法会被自动注入到当前类中,相当于间接完成了接口的方法实现要求,所以不需要在User子类里重复编写这些方法。
具体细节:
MustVerifyEmailTrait包含了接口要求的hasVerifiedEmail()、markEmailAsVerified()、sendEmailVerificationNotification()、getEmailForVerification()四个方法的完整实现- 当
User类继承Authenticatable时,如果父类已经引入该Trait,或者子类自己通过use关键字引入,这些方法就会成为User类的一部分 - PHP允许通过Trait来满足接口的实现要求,只要类或其继承链中的类引入的Trait覆盖了接口的所有方法,就无需手动重写
内容的提问来源于stack exchange,提问作者mahdi_sheykh
相关产品推荐
相关产品推荐

