0

我需要在 OOP 中实现事件侦听器模型。现在我有EventInterfaceListenerInterface。但我想将事件传递给侦听器,如:

interface ListenerInterface {
  public function listen(EventInterface $event);
}

但即使Event我传递给 Listener implements ,我也不能这样做EventInterface。那我该怎么办?我想把它抽象化以方便使用。

来自 PhpStorm 的屏幕截图: 在此处输入图像描述

4

1 回答 1

1

SendUserNotificationListener 遵守由ListenerInterface.

该错误有助于告诉您这一点。如果您尝试运行此代码,您将收到一个致命错误并且您的脚本将崩溃。

如果你有几个这样的接口:

interface ParentInterface {
    public function foo();
}

interface ChildInterface extends ParentInterface {
    public function bar();
}

interface AnotherChildInterface extends ParentInterface {
    public function baz();
}

interface OriginalHandlerInterface
{
    public function handle(ParentInterface $a): string;
}

任何实现的类都OriginalHandlerInterfce需要完全遵循它

例如

class OriginalImplementor implements OriginalHandlerInterface
{
    public function handle(ParentInterface $a) : string
    {
        return class_name($a);
    }
}

如果你试图让实现在参数上使用协方差,它会失败,因为实现不会遵循接口。例如

class WrongOriginalImplementor implements OriginalHandlerInterface
{
    public function handle(ChildInterface $a) : string
    {
        return class_name($a);
    }
}

这样做的逻辑简单而合理。如果有人正在使用您创建的声明该 implements 的类OriginalHandlerInterface,则该用户根本不需要查看您的实现,他们只需要查看接口即可。

如果原始接口声明handle()需要一个ParentInterface对象,这意味着我可以将来自实现的类的对象传递给它ParentInterface,但来自实现ChildInterface或的类的对象AnotherChildInterface也是有效的。

另一方面,如果您的实现能够说handle(ChildInterface $a),那么用户将背叛他们的期望,因为他们将无法handle()从实现的类中传递对象AnotherChildInterface,尽管根据OriginalHandlerInterface.

另一方面,如果你有这个界面:

interface AnotherHandlerInterface
{ 
    public function handle(ChildInterface $a): string;
}

您的实现可以在参数上使用逆变。handle()他们可以指定限制较少的参数类型。例如:

class ContravariantImplementor implements AnotherHandlerInterface
{
    public function handle(ParentInterface $a): string {
        return class_name($a);
    }
}

这个实现,尽管不遵循点,是有效的。同样,如果您考虑一下,同样的逻辑也适用:您的班级的消费者可以查看AnotherHandlerInterface并看到handle()预期的ChildInterface. 因此,如果遵循原始合同,他们将永远不会被您的实施绊倒。

您的实现限制较少,并接受原始接口不接受的对象,但这很好,因为协变和逆变规则允许它。

请注意,协变和逆变支持在 PHP 中是相当新的,并且仅在 PHP 7.4 中添加

你可以看到上面的代码在这里工作(包括错误)

于 2020-02-13T07:50:38.403 回答