只有存在时才实现接口?

Implements Interface only if exists?

我正在尝试找到一种仅在该接口可用时才实现该接口的方法。

有问题的接口是

PrestaShop\PrestaShop\Core\Module\WidgetInterface

来自 Prestashop。它在模块中使用。

问题是,为了与多个版本的 Prestashop 兼容,代码必须处理 WidgetInterface 不存在的情况。

我在想测试接口是否存在,然后导入它,像这样:

if (interface_exists('PrestaShop\PrestaShop\Core\Module\WidgetInterface')) {
    use PrestaShop\PrestaShop\Core\Module\WidgetInterface
} else {
    interface WidgetInterface {}
}

当然,在 if 语句中使用 use 是不可能的。

然后我尝试做一些 try/catch,但这是同样的问题(可惜不是 Python)。

如何才能 implements WidgetInterface 仅在可用时?

你不能像你说的那样动态实现接口,但你可以编写自己的接口,并且 require 如果另一个接口不存在,则只使用它。

即:您的界面将类似于 widget_interface.php,或者您想要的任何名称,只要它不符合 PSR-0/4 或以您通常使用的任何方式自动加载即可。

<?php    

namespace PrestaShop\PrestaShop\Core\Module;

/**
 * This is the replacement interface, using the same namespace as the Prestashop one
 */
interface WidgetInterface
{
}

然后,在您的 class 中,您可以执行以下操作:

<?php

namespace App;

if (!interface_exists('\PrestaShop\PrestaShop\Core\Module\WidgetInterface')) {
    require __DIR__ . '/path/to/widget_interface.php';
}

class WhateverClass implements \PrestaShop\PrestaShop\Core\Module\WidgetInterface
{

}

仅当 Prestashop 界面不存在时才会加载您的替换界面。

是的,您不能将 use 放在 if 块中,但是 use 只是为 class 设置了一个别名。它不会尝试加载 class。因此它可以安全地位于 if 块之外。

并且您可以if.

中定义class或接口本身

This 是 Symfony 处理这个确切问题的方式,继承自一个可能不存在的接口:

namespace Symfony\Contracts\EventDispatcher;

use Psr\EventDispatcher\EventDispatcherInterface as PsrEventDispatcherInterface;

if (interface_exists(PsrEventDispatcherInterface::class)) {
    interface EventDispatcherInterface extends PsrEventDispatcherInterface
    {
        public function dispatch($event);
    }
} else {
    interface EventDispatcherInterface
    {
        public function dispatch($event);
    }
}

就个人而言,为了保持整洁并包含在一个地方,我会像这样定义你自己的接口,如果可用的话,它继承自 PrestaShop 接口,或者提供自己的实现,然后让你的 class 继承自那个。