在 PHP 中使一个接口覆盖它从另一个接口继承的方法

发布于 2024-07-04 07:30:45 字数 1859 浏览 8 评论 0原文

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 的所有方法。 但是,我需要 iVendor 和 iShipper 中的 __construct 函数是唯一的。 我知道我可以取出 $shipment = null ,但是创建 Shippers 就不那么方便了(只需在实例化时传入vendors_no 和发货)。

有人知道如何进行这项工作吗? 我的后备方案是在实例化 Shipper 后通过调用 $shipper->setShipment($shipment); 来设置发货,但我希望有一种方法可以避免必须这样做这样做...

为好奇的人提供更多解释:
FedEx 对象具有访问 FedEx 站点(使用 cURL)并获取相关货件估计值的方法。 我有一个 UPS 对象、一个 BAXGlobal 对象、一个 Conway 对象等。每个对象都有完全不同的方法来实际获取运费估算,但系统需要知道的是它们是“托运人”,并且列出的方法接口可在它们上调用(因此它可以完全相同地对待它们,并在调用 getTransitX() 的“shippers”数组中循环遍历它们,以找到货运的最佳托运人)。

每个“托运人”也是一个“供应商”,并且在系统的其他部分(获取和放入数据库等)也被视为“供应商”。我们的数据设计是一堆垃圾,所以 FedEx 是与 Dunder Mifflin 等公司一起存储在“供应商”表中,这意味着它可以拥有所有其他供应商的所有属性,但需要 iShipper 提供的额外属性和方法。

Is there a way in PHP to overwrite a method declared by one interface in an interface extending that interface?

The Example:

I'm probably doing something wrong, but here is what I have:

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);
}

Normally in PHP, when you extend something, you can overwrite any method contained therein (right?). However, when one interface extends another, it won't let you. Unless I'm thinking about this wrong... When I implement the iShipper interface, I don't have to make the Shipper object extend the Vendor object (that implements the iVendor interface). I just say:

class FedEx implements iShipper{}

and make FedEx implement all of the methods from iVendor and iShipper. However, I need the __construct functions in iVendor and iShipper to be unique. I know I could take out the $shipment = null, but then it wouldn't be as convenient to create Shippers (by just passing in the vendors_no and the shipment while instantiating).

Anyone know how to make this work? My fallback is to have to set the shipment by calling $shipper->setShipment($shipment); on the Shipper after I instantiate it, but I'm hoping for a way to get around having to do that...

A little more explanation for the curious:
The FedEx Object has methods that go to the FedEx site (using cURL) and gets an estimate for the Shipment in question. I have a UPS Object, a BAXGlobal Object, a Conway Object, etc. Each one has COMPLETELY different methods for actually getting the shipping estimate, but all the system needs to know is that they are a "shipper" and that the methods listed in the interface are callable on them (so it can treat them all exactly the same, and loop through them in a "shippers" array calling getTransitX() to find the best shipper for a shipment).

Each "Shipper" is also a "Vendor" though, and is treated as such in other parts of the system (getting and putting in the DB, etc. Our data design is a pile of crap, so FedEx is stored right alongside companies like Dunder Mifflin in the "Vendors" table, which means it gets to have all the properties of every other Vendor, but needs the extra properties and methods supplied by iShipper).

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

感悟人生的甜 2024-07-11 07:30:45

@cmcculloh 是的,在 Java 中,你不在接口中定义构造函数。 这使您既可以扩展接口,又可以拥有一个实现多个接口的类(两者都是允许的,并且在许多情况下非常有用),而不必担心必须满足特定的构造函数。

编辑:

这是我的新模型:

A。 每个接口不再有构造函数。
B. 所有托运人(UPS、FedEx 等)现在都实现 iShipper(它扩展了 iVendor)并扩展了抽象类 Shipper(其中定义了托运人的所有常见非抽象方法,getName()、getZip() 等)。
C. 每个 Shipper 都有自己独特的 _construct 方法,该方法会覆盖 Shipper 中包含的抽象 __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...
}

感谢您的帮助!
ps。 因为我现在已将其添加到“您的”答案中,如果您不喜欢/认为应该有所不同,请随意更改它......

@cmcculloh Yeah, in Java you don't define constructors in Interfaces. This allows you to both extend interfaces and also have a class that implements multiple interfaces (both allowed, and very useful in many cases) without worrying about having to satisfy a particular constructor.

EDIT:

Here's my new model:

A. Each interface no longer has a constructor method.
B. All Shippers (UPS, FedEx, etc) now implement iShipper (which extends iVendor) and extend the abstract class Shipper (which has all common non-abstract methods for shippers defined in it, getName(), getZip() etc).
C. Each Shipper has it's own unique _construct method which overwrites the abstract __construct($vendors_no = null, $shipment = null) method contained in Shipper (I don't remember why I'm allowing those to be optional now though. I'd have to go back through my documentation...).

So:

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...
}

Thanks for the help!
ps. since I have now added this to "your" answer, if there is something about it you don't like/think should be different, feel free to change it...

峩卟喜欢 2024-07-11 07:30:45

您可以放弃构造函数并将它们放入每个单独的类中。 那么你所拥有的是每个类都有自己的 __construct,这可能是相同的,具体取决于它是托运人还是供应商。 如果您只想定义一次这些构造,我认为您不想走这条路。

我认为你想要做的是创建一个实现供应商的抽象类,以及一个实现托运人的抽象类。 在那里您可以以不同的方式定义构造函数。

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

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

You could drop off the constructor and just put them in each individual class. Then what you have is each class has its own __construct, which is probably the same depending on if it is a shipper or vendor. If you want to only have those constructs defined once I don't think you want to go down that route.

What I think you want to do is make an abstract class that implements vendor, and one that implements shipper. There you could define the constructors differently.

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

abstract class Shipper implements iShipper {
    public function __construct() {
        something();
    }
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文