抽象类或接口,其中声明方法签名允许子类的类型提示

带有子对象参数的 add 方法与调用父类的实现不匹配。有没有解决的办法?


除非有更好的方法,否则我的计划是为 Collections 创建一个界面,如下所示:


interface Collection {

   public function add( ValueObjects $obj ) : bool;

}


abstract class ValueObjects {}


class User extends ValueObjects {

}

然后我在 User 值对象的具体集合上实现 Collection 接口。


class UserCollection implements Collection {

  public function add( User $user ) : bool 

  {

     return true;

  }

}

这显然会引发一个错误,即Declaration should be compatible with Collection. 有没有办法实现相同的结果以允许签名中的子对象?我尝试了抽象类,但没有结果。


如果我不必扩展抽象的 ValueObjects 类会更好。


感谢您分享您的知识 SO 社区。


PS...回顾了这个问题,装饰器和组合模式。我要么错过了,要么我的问题有点不同。



FFIVE
浏览 154回答 2
2回答

缥缈止盈

简短的回答是“否”,因为 PHP 中缺少泛型类。要解决此问题,您应该ValueObjects在实现类中继续使用抽象类型(此处为),然后自己检查实际类型。class UserCollection implements Collection {  public function add( ValueObjects $obj ) : bool   {     if (!($obj instanceof User)) {          throw new RuntimeException('...');     }     /** @var User $obj */     // The above comment make your IDE know the $obj is a `User` instance     // your actual logic     return true;  }}一个小提示,您不需要在 PHP中将$obj对象从ValueObjectsto 转换User。@var上面代码中的phpDoc 内联注释行仅告诉 IDE 这$obj是一个User实例并支持User方法的自动完成。没有它,PHP 脚本仍然运行。

温温酱

我会按照这些思路争论一些事情。请注意我如何扩展客观收集的核心概念,同时作为一个自我验证的主题。然后我构成这些各种构建成可知,混凝土组合。interface Transportable {};interface User {};interface Collected{    public function isValid($item): bool;    // Contract, add is deterministic, require no return    public function add(Transportable $item): void;}trait SanityChecked{    public function isValid($item): bool    {        return true;    }}abstract class Collector implements Collected{    use SanityChecked;    private $items = [];    public function add(Transportable $item): void    {        if ($this->isValid($item) && $this->items[] = $item) {            return;        }        throw new Exception('This is the not the droid we were looking for.');    }}class Users extends Collector{    public function isValid($test): bool    {        return $test instanceof User;    }}这可以被嘲笑为:$users = new Users();$users->add(new class() implements Transportable, User {});echo 'Added first!'.PHP_EOL;$users->add(new class() implements User {}); // Sorry, error.echo 'Added second!'.PHP_EOL;https://3v4l.org/O2qfJ另一种看待它的方式是进一步扩展 trait 的行为:trait ValidatesAsUser{    public function isValid(Transportable $user): bool    {        return $user instanceof User;    }}class PortalUsers extends Collector{    use ValidatesAsUser;}class ContentEditors extends PortalUsers {}class Authors extends ContentEditors {}class AuthorsWithPublishedStoriesByRating extends Authors {}我认为关于预测的最后一部分特别有趣。
打开App,查看更多内容
随时随地看视频慕课网APP