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

Есть ли способ в PHP перезаписать метод, объявленный одним интерфейсом, в интерфейсе, расширяющем этот интерфейс?

Пример:

Я, наверное, что-то не так делаю, но вот что у меня:

interface iVendor{
    public function __construct($vendors_no = null);
    public function getName();
    public function getVendors_no();
    public function getZip();
    public function getCountryCode();
    public function setName($name);
    public function setVendors_no($vendors_no);
    public function setZip($zip);
    public function setCountryCode($countryCode);
}

interface iShipper extends iVendor{
    public function __construct($vendors_no = null, $shipment = null);
    public function getTransitTime($shipment = null);
    public function getTransitCost($shipment = null);
    public function getCurrentShipment();
    public function setCurrentShipment($shipment);
    public function getStatus($shipment = null);
}

Обычно в PHP, когда вы что-то расширяете, вы можете перезаписать любой содержащийся в нем метод (верно?). Однако, когда один интерфейс расширяет другой, это не позволит вам. Если я не думаю об этом неправильно ... Когда я реализую интерфейс iShipper, мне не нужно заставлять объект Shipper расширять объект Vendor (который реализует интерфейс iVendor). Я просто говорю:

class FedEx implements iShipper{}

и заставить FedEx реализовать все методы iVendor и iShipper. Однако мне нужно, чтобы функции __construct в iVendor и iShipper были уникальными. Я знаю, что могу удалить $shipment = null, но тогда было бы не так удобно создавать Shippers (просто передав vendors_no и shipment при создании экземпляра).

Кто-нибудь знает, как заставить эту работу? Мой запасной вариант - установить отгрузку, позвонив в $shipper->setShipment($shipment); на грузоотправителя после того, как я создам его экземпляр, но я надеюсь найти способ обойтись без этого ...

Еще немного пояснений для любопытных:
У объекта FedEx есть методы, которые переходят на сайт FedEx (используя cURL) и получают оценку рассматриваемой поставки. У меня есть объект UPS, объект BAXGlobal, объект Conway и т. д. У каждого из них есть ПОЛНОСТЬЮ разные методы для фактического получения сметы доставки, но все, что нужно знать системе, это то, что они являются «грузоотправителем» и что методы, перечисленные в интерфейс вызывается на них (так что он может обрабатывать их все одинаково и перебирать их в массиве «shippers», вызывая getTransitX(), чтобы найти лучшего отправителя для отгрузки).

Каждый «Грузоотправитель» также является «Продавцом» и рассматривается как таковой в других частях системы (получение и ввод в БД и т. д. Наш дизайн данных - это куча мусора, поэтому FedEx хранится рядом с такими компаниями, как Dunder Mifflin в таблице «Продавцы», что означает, что он будет иметь все свойства любого другого поставщика, но ему потребуются дополнительные свойства и методы, предоставляемые iShipper).

Мой опыт работы с объектно-ориентированным PHP ограничен, но действительно ли вам нужно определять конструктор в определениях интерфейса? Во всяком случае, это вообще не практика в Java.

Ryan Ahearn 19.08.2008 17:48
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Symfony Station Communiqué - 7 июля 2023 г
Symfony Station Communiqué - 7 июля 2023 г
Это коммюнике первоначально появилось на Symfony Station .
Оживление вашего приложения Laravel: Понимание режима обслуживания
Оживление вашего приложения Laravel: Понимание режима обслуживания
Здравствуйте, разработчики! В сегодняшней статье мы рассмотрим важный аспект управления приложениями, который часто упускается из виду в суете...
Установка и настройка Nginx и PHP на Ubuntu-сервере
Установка и настройка Nginx и PHP на Ubuntu-сервере
В этот раз я сделаю руководство по установке и настройке nginx и php на Ubuntu OS.
Коллекции в Laravel более простым способом
Коллекции в Laravel более простым способом
Привет, читатели, сегодня мы узнаем о коллекциях. В Laravel коллекции - это способ манипулировать массивами и играть с массивами данных. Благодаря...
Как установить PHP на Mac
Как установить PHP на Mac
PHP - это популярный язык программирования, который используется для разработки веб-приложений. Если вы используете Mac и хотите разрабатывать...
2
1
2 359
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

@cmcculloh Да, в Java вы не определяете конструкторы в интерфейсах. Это позволяет вам как расширять интерфейсы, так и иметь класс, реализующий несколько интерфейсов (как разрешенных, так и очень полезных во многих случаях), не беспокоясь о необходимости удовлетворения конкретного конструктора.

Обновлено:

Вот моя новая модель:

A. У каждого интерфейса больше нет метода конструктора.
B. Все грузоотправители (UPS, FedEx и т. д.) Теперь реализуют iShipper (который расширяет iVendor) и расширяют абстрактный класс Shipper (который имеет все общие не абстрактные методы для грузоотправителей, определенные в нем, getName (), getZip () и т. д.).
C. У каждого грузоотправителя есть собственный уникальный метод _construct, который перезаписывает абстрактный метод __construct ($ vendors_no = null, $ shipment = null), содержащийся в грузоотправителе (я не помню, почему я позволяю им быть необязательными сейчас. Я ' мне придется вернуться к моей документации ...).

Так:

interface iVendor{
    public function getName();
    public function getVendors_no();
    public function getZip();
    public function getCountryCode();
    public function setName($name);
    public function setVendors_no($vendors_no);
    public function setZip($zip);
    public function setCountryCode($countryCode);
}

interface iShipper extends iVendor{
    public function getTransitTime($shipment = null);
    public function getTransitCost($shipment = null);
    public function getCurrentShipment();
    public function setCurrentShipment($shipment);
    public function getStatus($shipment = null);
}

abstract class Shipper implements iShipper{  
    abstract public function __construct($vendors_no = null, $shipment = null);  
    //a bunch of non-abstract common methods...  
}

class FedEx extends Shipper implements iShipper{  
    public function __construct($vendors_no = null, $shipment = null){
        //a bunch of setup code...
    }
    //all my FedEx specific methods...
}

Спасибо за помощь!
пс. так как я добавил это к «вашему» ответу, если что-то в этом вам не нравится / вы думаете, что должно быть по-другому, не стесняйтесь менять это ...

Вы можете отказаться от конструктора и просто поместить его в каждый отдельный класс. Тогда у вас есть то, что каждый класс имеет свою собственную конструкцию __construct, которая, вероятно, одинакова в зависимости от того, является ли он отправителем или поставщиком. Если вы хотите, чтобы эти конструкции были определены только один раз, я не думаю, что вы хотите идти по этому пути.

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

abstract class Vendor implements iVendor {
    public function __construct() {
        whatever();
    }
}

abstract class Shipper implements iShipper {
    public function __construct() {
        something();
    }
}

Другие вопросы по теме