我经常发现自己希望能够让 trait 实现一个接口,这样当我将 trait 添加到类中时,我可以知道满足了 trait 的要求。例如,在 Laravel 中,我将为我的许多关系创建特征,如下所示:
trait HasOwner
{
public function owner()
{
return $this->belongsTo(User::class);
}
}
Run Code Online (Sandbox Code Playgroud)
在 Laravel 的情况下,我可以非常确定我添加它的每个模型都将有一个 ownsTo 方法,但是我仍然觉得我应该能够强制执行这个。
我知道强制执行此操作的唯一方法是使用 HasOwnerInterface 或 HasRelationshipsInterface 来支持它,但事实上,当我添加特性时未能添加它会防止它发出吱吱声,感觉就像在车上安装了安全气囊,但您需要这样做每次启动发动机时打开。
这是我认为将是完美的:
trait HasOwner expects RelationshipInterface
{
public function owner()
{
return $this->belongsTo(User::class);
}
}
interface RelationshipInterface
{
public function belongsTo(Model $model): Relationship;
}
class Property implements RelationshipInterface
{
use HasOwner;
}
Run Code Online (Sandbox Code Playgroud)
我应该为此使用另一种设计模式,还是我应该鼓起勇气,开始与 PHP 核心团队为此而战以添加它?
请记住,特征本质上只是“自动复制粘贴”的语法糖,因此您不能直接将典型的 OOP 技术应用于它们。按照目前的情况(2021 年 6 月),通过对具有抽象方法的使用特征的类施加至少一些要求,您可能会更接近:
\n\n\n特征支持使用抽象方法,以便对展示类施加\n要求。支持公共、受保护和私有\n方法。在 PHP 8.0.0 之前,仅支持公共和受保护的\n抽象方法。
\n
<?php\ntrait Hello {\n public function sayHelloWorld() {\n echo \'Hello\'.$this->getWorld();\n }\n abstract public function getWorld();\n}\n\nclass MyHelloWorld {\n private $world;\n use Hello;\n public function getWorld() {\n return $this->world;\n }\n public function setWorld($val) {\n $this->world = $val;\n }\n}\n?>\nRun Code Online (Sandbox Code Playgroud)\n作为旁注,有一个现有的用于实现接口的特征的 RFC,于 2016 年提交(!)。这是关键引用:
\n\n\n第一个建议是允许一个特征声明它\n实现一个接口。让特征声明它实现\n接口使得接口\n(规范)和特征(实现)之间的关系变得明确。
\n该特征必须实现所有接口实现的每个方法。如果不这样做将是一个致命的错误。方法声明必须与接口兼容。部分或全部 Trait\xe2\x80\x99 实现方法可能是抽象的,其中包含提供方法实现的 Trait 的类(类似于实现接口的抽象类)。
\n
不过,到目前为止,该 RFC 的进展甚微。不清楚原因;虽然提案 2 存在一个悬而未决的问题(关于将接口从特征传播到类),但提案 1 似乎没有任何问题。预计该方案也不会发生重大更改。
\n| 归档时间: |
|
| 查看次数: |
66 次 |
| 最近记录: |