جعل إحدى الواجهات تقوم بالكتابة فوق طريقة ترثها من واجهة أخرى في PHP

StackOverflow https://stackoverflow.com/questions/16155

  •  08-06-2019
  •  | 
  •  

سؤال

هل هناك طريقة في 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, ، ولكن بعد ذلك لن يكون من المناسب إنشاء شركات الشحن (بمجرد تمرير البائعين_لا والشحنة أثناء إنشاء مثيل).

هل يعرف أحد كيفية جعل هذا العمل؟خياري الاحتياطي هو أن أضطر إلى ضبط الشحنة عن طريق الاتصال $shipper->setShipment($shipment); على الشاحن بعد أن أقوم بإنشاء مثيل له، ولكنني آمل أن أجد طريقة للالتفاف حول الاضطرار إلى القيام بذلك ...

مزيد من التوضيح للفضوليين:
يحتوي كائن FedEx على طرق تنتقل إلى موقع FedEx (باستخدام cURL) وتحصل على تقدير للشحنة المعنية.لدي كائن UPS، وكائن BAXGlobal، وكائن Conway، وما إلى ذلك.كل واحد لديه طرق مختلفة تمامًا للحصول على تقدير الشحن فعليًا، ولكن كل ما يحتاج النظام إلى معرفته هو أنهم "شاحن" وأن الطرق المدرجة في الواجهة قابلة للاستدعاء عليها (حتى يتمكن من التعامل معها جميعًا بنفس الطريقة تمامًا ، وقم بالتكرار من خلالهم في استدعاء صفيف "الشاحنين". getTransitX() للعثور على أفضل شاحن للشحنة).

ومع ذلك، فإن كل "شاحن" هو أيضًا "بائع"، ويتم التعامل معه على هذا النحو في أجزاء أخرى من النظام (الحصول على قاعدة البيانات ووضعها، وما إلى ذلك).تصميم البيانات الخاص بنا عبارة عن كومة من الهراء، لذلك يتم تخزين FedEx جنبًا إلى جنب مع شركات مثل Dunder Mifflin في جدول "الموردين"، مما يعني أنها ستحصل على جميع خصائص كل بائع آخر، ولكنها تحتاج إلى الخصائص والأساليب الإضافية التي توفرها iShipper ).

هل كانت مفيدة؟

المحلول

@cmcculloh نعم، في Java لا تحدد المنشئات في الواجهات.يتيح لك هذا توسيع الواجهات والحصول أيضًا على فئة تنفذ واجهات متعددة (كلاهما مسموح به ومفيد جدًا في كثير من الحالات) دون القلق بشأن الاضطرار إلى إرضاء مُنشئ معين.

يحرر:

هذا هو نموذجي الجديد:

أ.لم تعد كل واجهة تحتوي على طريقة إنشاء.
ب.تقوم جميع شركات الشحن (UPS وFedEx وما إلى ذلك) الآن بتطبيق iShipper (الذي يمتد إلى iVendor) وتوسيع فئة الشاحن المجردة (التي تحتوي على جميع الطرق غير المجردة الشائعة لشركات الشحن المحددة فيها، getName()، getZip() وما إلى ذلك).
ج.كل شركة شحن لديها طريقة _construct فريدة خاصة بها والتي تحل محل الطريقة المجردة __construct($vendors_no = null, $shipment = null) الموجودة في Shipper (لا أتذكر سبب السماح لها بأن تكون اختيارية الآن بالرغم من ذلك.يجب أن أعود من خلال وثائقي ...).

لذا:

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

شكرا للمساعدة!
ملاحظة.بما أنني أضفت هذا الآن إلى إجابتك، إذا كان هناك شيء لا يعجبك/تعتقد أنه يجب أن يكون مختلفًا، فلا تتردد في تغييره...

نصائح أخرى

يمكنك ترك المنشئ ووضعه في كل فئة على حدة.ثم ما لديك هو أن كل فئة لها __البنية الخاصة بها، والتي ربما تكون هي نفسها اعتمادًا على ما إذا كانت شركة شحن أو بائع.إذا كنت تريد تحديد هذه التركيبات مرة واحدة فقط، فلا أعتقد أنك تريد السير في هذا الطريق.

ما أعتقد أنك تريد القيام به هو إنشاء فئة مجردة تنفذ البائع، وأخرى تنفذ الشاحن.هناك يمكنك تحديد المنشئين بشكل مختلف.

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

abstract class Shipper implements iShipper {
    public function __construct() {
        something();
    }
}
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top