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
, しかし、そうすると、シッパーを作成するのはそれほど便利ではなくなります(インスタンス化中にvenders_noと出荷を渡すだけです)。
これを機能させる方法を知っている人はいますか?私のフォールバックは、電話して出荷を設定する必要があることです $shipper->setShipment($shipment);
インスタンス化した後にシッパー上で実行しますが、それを回避する方法を望んでいます...
好奇心旺盛な人のためにもう少し説明すると、
FedEx オブジェクトには、(cURL を使用して) FedEx サイトにアクセスし、問題の貨物の見積もりを取得するメソッドがあります。UPS オブジェクト、BAXGlobal オブジェクト、Conway オブジェクトなどがあります。それぞれが実際に配送見積りを取得するための完全に異なるメソッドを持っていますが、システムが知っておく必要があるのは、それらが「出荷者」であること、およびインターフェースにリストされているメソッドがそれらの出荷者に対して呼び出し可能であることだけです(したがって、システムはそれらをすべてまったく同じに扱うことができます)を呼び出し、「shippers」配列でそれらをループします。 getTransitX()
貨物に最適な配送業者を見つけるため)。
ただし、各「シッパー」は「ベンダー」でもあり、システムの他の部分 (DB の取得や配置など) ではそのように扱われます。私たちのデータ設計はゴミの山なので、FedEx は「ベンダー」テーブルでダンダー ミフリンのような企業と並んで保存されています。つまり、他のすべてのベンダーのプロパティをすべて持つことができますが、iShipper によって提供される追加のプロパティとメソッドが必要です。 )。
解決
@cmccullo そうですね、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。これを「あなたの」回答に追加したので、気に入らない点がある場合/異なるべきだと思う場合は、お気軽に変更してください...
他のヒント
コンストラクターを削除して、それぞれのクラスに配置することもできます。次に、各クラスが独自の __construct を持っていることになります。これは、出荷者かベンダーかに応じておそらく同じです。これらの構成要素を一度だけ定義したい場合は、そのルートをたどろうとは思わないでしょう。
あなたがやりたいことは、vendorを実装する抽象クラスとshipperを実装する抽象クラスを作成することです。そこではコンストラクターを別の方法で定義できます。
abstract class Vendor implements iVendor {
public function __construct() {
whatever();
}
}
abstract class Shipper implements iShipper {
public function __construct() {
something();
}
}