为了账号安全,请及时绑定邮箱和手机立即绑定

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

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

PHP
FFIVE 2021-11-13 15:00:08
带有子对象参数的 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...回顾了这个问题,装饰器和组合模式。我要么错过了,要么我的问题有点不同。
查看完整描述

2 回答

?
缥缈止盈

TA贡献2041条经验 获得超4个赞

简短的回答是“否”,因为 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 脚本仍然运行。


查看完整回答
反对 回复 2021-11-13
?
温温酱

TA贡献1752条经验 获得超4个赞

我会按照这些思路争论一些事情。请注意我如何扩展客观收集的核心概念,同时作为一个自我验证的主题。然后我构成这些各种构建成可知,混凝土组合。


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

我认为关于预测的最后一部分特别有趣。


查看完整回答
反对 回复 2021-11-13
  • 2 回答
  • 0 关注
  • 150 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信