Использование интерфейсов в PHP

Я прихожу из С#, и я изо всех сил пытаюсь выработать PHP-способ сделать мой код расширяемым.

Давайте скажем, например, у меня есть функция, которая вычисляет мое рекомендуемое суточное потребление пищи. Он смотрит на витамины, калории, минералы и т.д.

Я хочу иметь много разных продуктов питания, которые я использую в своем приложении, и различные функции, которые рассматривают различные аспекты пищи, поэтому я реализую интерфейс IFoodNutrition и делаю свои классы пищи, которые я хочу быть совместимыми с моей функцией реализовать его. Затем я объявляю, что моя функция принимает его как arg

function GetRda(IFoodNutrition $food){}

В С# я бы указал все свойства, которые мне нужно использовать в интерфейсе, поэтому я знаю, что любой класс, который реализует это, будет совместим с этой функцией.

Что вызывает у меня боль в голове, так это то, что PHP допускает только сигнатуры методов в интерфейсах.

Мои проблемы - это, очевидно, сдвиг парадигмы. Я не уверен, что эквивалентный шаблон в PHP. Я прочитал документацию, и я не вижу подобного как альтернативу, если вы не наследуете от абстрактного класса, но тогда вы можете наследовать только один класс, чтобы он не работал одинаково.

Поскольку PHP не является типичным, мне не нужно создавать интерфейс. Кто-то может просто отправить какой-либо объект методу, и если он обладает необходимыми свойствами в правильном формате, он будет работать. Это просто не кажется мне правильным, хотя я так привык к тому, чтобы излагать, как нужно взаимодействовать с интерфейсами.

Я чувствую, что по крайней мере должен быть какой-то дополнительный шаг в середине, где объект проверяется, и какая-то очевидная структура, которую разработчик может посмотреть, а затем реализовать свой собственный класс интуитивно и увидеть ошибки до выполнения.

Существует ли определенный шаблон в PHP?

Ответ 1

PHP допускает только сигнатуры методов в интерфейсах.

Это верно. Тем не менее, ничто не мешает вам создавать традиционные геттеры и сеттеры для свойств как часть интерфейса. Выполнение этих тезисов для основных деталей реализации.

Кто-то может просто отправить какой-либо объект методу, и если он имеет необходимые свойства в правильном формате, он будет работать.

Это неверно. У вас тип-hinted аргумент с IFoodNutrition $food. PHP будет генерировать фатальную ошибку, если эта функция получает объект, который не реализует интерфейс IFoodNutrition.

Ответ 2

Мои знания PHP по-прежнему ограничены, но я попробую пару ответов о том, как я буду решать эту проблему.

1. быстро и грязно (не рекомендуется, имхо, большой нет-нет)

принять все на входе, сбой с исключением, если вход недействителен.

    function getRda ($food) {

        if (!($food instanceof IInterface)) {
           throw new \Exception('function argument should be instance of IInterface');

        }

    //... do your magic
    }

2. предложить геттеры и сеттеры через интерфейс

В интерфейсе предположим наличие свойства (например, getMinerals для $minerals)

3. используйте признак

Хотя это не поможет вам с установлением контракта между взаимодействием объектов, это поможет вам сохранить код DRY

например.

trait Food 
{
   protected $minerals;
   public function getMinerals ()
     {
        return $this->minerals;
     }
}

то в каждом классе вам требуется множественное наследование (эквивалент, скажем, расширения двух абстрактных классов), используйте вышеприведенную черту.

Ответ 3

Вы не можете определить свойства в интерфейсе в php.

Это имеет смысл, потому что функция интерфейса - это указать API, а не реализацию.