Реализует интерфейс, только если существует?
Я пытаюсь найти способ реализовать интерфейс только тогда, когда этот интерфейс доступен.
Интерфейс в вопросе является
PrestaShop\PrestaShop\Core\Module\WidgetInterface
Из Престашопа. Он используется в модуле.
Дело в том, что для совместимости с несколькими версиями Prestashop код должен обрабатывать случай, когда WidgetInterface
не существует.
Я думал в тестировании существования интерфейса и импортировать его после, как это:
if (interface_exists('PrestaShop\PrestaShop\Core\Module\WidgetInterface')) {
use PrestaShop\PrestaShop\Core\Module\WidgetInterface
} else {
interface WidgetInterface {}
}
Но, конечно, невозможно использовать use
внутри оператора if.
Затем я попытался сделать некоторые попытки / поймать, но это та же проблема (жаль, что это не Python).
Как я могу сделать, чтобы implements WidgetInterface
только тогда, когда он доступен?



Ответы - Реализует интерфейс, только если существует? / Implements Interface only if exists?

18.09.2019 07:10:33
Вы не можете реализовать интерфейс динамически, как вы говорите, но вы можете написать свой собственный интерфейс и require
его только в том случае, если другой не существует.
Ie: ваш интерфейс будет чем-то вроде 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
{
}
Затем, в вашем классе, вы можете сделать следующее:
<?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 one не существует.

19.09.2019 05:29:28
Правда, вы не можете use
внутри блока if
, но use
просто устанавливает псевдоним для класса. Он не пытается загрузить класс. Таким образом, он может безопасно находиться за пределами блока if
.
И вы можете определить класс или сам интерфейс внутри if
.
Вот как 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
, если он доступен, или предоставляет свою собственную реализацию, а затем ваш класс наследует от этого.