Faire en sorte qu'une interface écrase une méthode dont elle hérite d'une autre interface en PHP

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

  •  08-06-2019
  •  | 
  •  

Question

Existe-t-il un moyen en PHP d'écraser une méthode déclarée par une interface dans une interface étendant cette interface ?

L'exemple:

Je fais probablement quelque chose de mal, mais voici ce que j'ai :

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

Normalement en PHP, lorsque vous étendez quelque chose, vous pouvez écraser n'importe quelle méthode qu'il contient (non ?).Cependant, lorsqu’une interface en étend une autre, elle ne vous le permet pas.À moins que j'y pense mal...Lorsque j'implémente l'interface iShipper, je n'ai pas besoin de faire en sorte que l'objet Shipper étende l'objet Vendor (qui implémente l'interface iVendor).Je dis juste:

class FedEx implements iShipper{}

et faites en sorte que FedEx implémente toutes les méthodes d'iVendor et d'iShipper.Cependant, j'ai besoin du __construct fonctions dans iVendor et iShipper pour être uniques.Je sais que je pourrais retirer le $shipment = null, mais il ne serait alors pas aussi pratique de créer des expéditeurs (en transmettant simplement le supplier_no et l'expédition lors de l'instanciation).

Quelqu'un sait comment faire fonctionner cela ?Ma solution de rechange est de devoir régler l'envoi en appelant $shipper->setShipment($shipment); sur l'expéditeur après l'avoir instancié, mais j'espère trouver un moyen de contourner ce problème...

Un peu plus d'explications pour les curieux :
L'objet FedEx dispose de méthodes qui accèdent au site FedEx (à l'aide de cURL) et obtiennent une estimation de l'envoi en question.J'ai un objet UPS, un objet BAXGlobal, un objet Conway, etc.Chacun a des méthodes COMPLÈTEMENT différentes pour obtenir le devis d'expédition, mais tout ce que le système a besoin de savoir, c'est qu'il s'agit d'un "expéditeur" et que les méthodes répertoriées dans l'interface peuvent être appelées sur lui (afin qu'il puisse les traiter toutes exactement de la même manière. , et parcourez-les dans un tableau "expéditeurs" appelant getTransitX() pour trouver le meilleur expéditeur pour un envoi).

Cependant, chaque « expéditeur » est également un « fournisseur » et est traité comme tel dans d'autres parties du système (obtention et mise dans la base de données, etc.Notre conception de données est un tas de conneries, donc FedEx est stocké aux côtés de sociétés comme Dunder Mifflin dans le tableau « Fournisseurs », ce qui signifie qu'il doit avoir toutes les propriétés de tous les autres fournisseurs, mais a besoin des propriétés et méthodes supplémentaires fournies par iShipper. ).

Était-ce utile?

La solution

@cmcculloh Oui, en Java, vous ne définissez pas de constructeurs dans les interfaces.Cela vous permet à la fois d'étendre les interfaces et également d'avoir une classe qui implémente plusieurs interfaces (toutes deux autorisées et très utiles dans de nombreux cas) sans vous soucier de devoir satisfaire un constructeur particulier.

MODIFIER:

Voici mon nouveau modèle :

UN.Chaque interface n'a plus de méthode constructeur.
B.Tous les expéditeurs (UPS, FedEx, etc.) implémentent désormais iShipper (qui étend iVendor) et étendent la classe abstraite Shipper (qui contient toutes les méthodes non abstraites courantes pour les expéditeurs, getName(), getZip() etc).
C.Chaque expéditeur a sa propre méthode _construct unique qui écrase la méthode abstraite __construct($vendors_no = null, $shipment = null) contenue dans Shipper (je ne me souviens pas pourquoi j'autorise celles-ci à être facultatives maintenant.Il faudrait que je reprenne ma documentation...).

Donc:

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

Merci pour l'aide!
p.s.puisque j'ai maintenant ajouté ceci à "votre" réponse, s'il y a quelque chose que vous n'aimez pas/pensez qu'il devrait être différent, n'hésitez pas à le changer...

Autres conseils

Vous pouvez déposer le constructeur et simplement le placer dans chaque classe individuelle.Ensuite, ce que vous avez, c'est que chaque classe a sa propre __construct, qui est probablement la même selon qu'il s'agit d'un expéditeur ou d'un fournisseur.Si vous souhaitez définir ces constructions une seule fois, je ne pense pas que vous souhaitiez emprunter cette voie.

Ce que je pense que vous voulez faire, c'est créer une classe abstraite qui implémente le fournisseur et une autre qui implémente l'expéditeur.Là, vous pouvez définir les constructeurs différemment.

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

abstract class Shipper implements iShipper {
    public function __construct() {
        something();
    }
}
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top