【发布时间】:2017-12-20 16:31:07
【问题描述】:
我已经在我的项目中实现了存储库模式,没有太多问题。为了避免重复自己,我实现了一个abstract 存储库类,我的所有存储库都扩展了它。每个存储库都有自己必须实现的interface。
我有类似于以下的代码,可以正常工作:
class Model {}
class User extends Model {}
abstract class AbstractRepository
{
protected $model;
public function find($id)
{
$class = $this->model;
return new $class();
}
}
interface UserRepositoryInterface
{
public function find($id);
}
class UserRepository extends AbstractRepository implements UserRepositoryInterface
{
protected $model = User::class;
}
我想开始在我的代码中使用返回类型声明,已升级到 PHP 7.1。所以我在AbstractRepository 的find 方法中添加了?Model 返回类型,在UserRepositoryInterface 中添加了?User 返回类型。
class Model {}
class User extends Model {}
abstract class AbstractRepository
{
protected $model;
public function find($id): ?Model
{
$class = $this->model;
return new $class();
}
}
interface UserRepositoryInterface
{
public function find($id): ?User;
}
class UserRepository extends AbstractRepository implements UserRepositoryInterface
{
protected $model = User::class;
}
现在,PHP 抱怨声明不兼容,这是我预料之中的。
致命错误:AbstractRepository::find($id) 的声明必须与 AbstractRepositoryInterface::find($id): ?Model in /Users/jonathon/Desktop/test.php 第 21 行兼容
在另一种语言中,例如 Java,我会考虑使用泛型来实现存储库,这将允许我在方法签名中使用泛型类型。
是否有可能让这个工作:
- 我为每个存储库都有一个接口和实现
- 我有一个由我的每个存储库扩展的抽象类,它完成了大部分工作。
- 我可以继续使用 PHP 7 的返回类型声明,为每个不同的存储库指定不同的返回类型(例如,
?User用于UserRepositoryInterface,?Product用于ProductRepositoryInterface)?
按照我现在的看法,我有几个选择:
- 不要费心使用返回类型。
- 将所有返回类型声明更改为
?Model,我的所有模型都对其进行了扩展。 - 重复自己,摆脱抽象类
【问题讨论】:
-
如果我正确理解您的问题,我相信这是关于覆盖抽象函数的返回类型?这现在可以在本月初发布的 PHP 7.2 中实现。
-
@AntonyD'Andrea 我无法理解,3v4l.org/5PlP0
-
@AntonyD'Andrea 感谢您的回答。我刚刚在本地安装了 PHP 7.2 并尝试运行上面的代码。我刚刚看到了同样的错误。然而,引入的变化看起来很有希望,我的第一反应是“就是这样!”。还是谢谢。
-
我也遇到了这个问题。似乎与参数类型提示的工作方式完全不一致。也刚刚升级到
7.2.2,我仍然看到同样的错误 - 在这里描述了我的情况:3v4l.org/PnIAZ - 以及我目前的工作(使用文档块)3v4l.org/D6HAu -
我也遇到了同样的问题。仅仅通过遵守 OOPs 继承规则,这应该可以工作,对吧?任何从抽象继承的 repo 都将通过 find-method 返回一个类型,该类型是 abstracts repo find-method 返回类型的扩展。因此它将履行合同。每个“用户”都足以作为“模型”等等。
标签: php oop generics return-type