【问题标题】:Making one interface overwrite a method it inherits from another interface in PHP使一个接口覆盖它从 PHP 中的另一个接口继承的方法
【发布时间】:2010-09-06 04:19:58
【问题描述】:

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 就不那么方便了(只需在实例化时传入 vendor_no 和货件)。

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

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

虽然每个“托运人”也是一个“供应商”,但在系统的其他部分(获取和放入数据库等)也是如此。我们的数据设计是一堆废话,所以联邦快递与 Dunder Mifflin 等公司一起存储在“供应商”表中,这意味着它可以拥有所有其他供应商的所有属性,但需要 iShipper 提供的额外属性和方法。

【问题讨论】:

  • 我的面向对象PHP经验有限,但真的需要在接口定义中定义构造函数吗?无论如何,这通常不是 Java 中的做法。

标签: php oop interface extends


【解决方案1】:

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

编辑:

这是我的新模型:

A.每个接口不再有构造方法。
B.所有托运人(UPS、FedEx 等)现在都实现了 iShipper(它扩展了 iVendor)并扩展了抽象类 Shipper(其中定义了托运人的所有常见非抽象方法,getName()、getZip() 等)。 em>
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。由于我现在已将此添加到“您的”答案中,如果您不喜欢/认为应该有所不同,请随时更改它...

【讨论】:

    【解决方案2】:

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

    我认为您想要做的是创建一个实现 vendor 的抽象类,以及一个实现shipper 的抽象类。在那里你可以不同地定义构造函数。

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-05-12
      • 2010-10-22
      • 2018-07-07
      • 2010-12-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多