Есть ли способ в 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).






@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();
}
}
Мой опыт работы с объектно-ориентированным PHP ограничен, но действительно ли вам нужно определять конструктор в определениях интерфейса? Во всяком случае, это вообще не практика в Java.