2 Stimmen

Überschreiben einer Methode, die eine Schnittstelle von einer anderen Schnittstelle erbt, in PHP

Gibt es in PHP eine Möglichkeit, eine von einer Schnittstelle deklarierte Methode in einer Schnittstelle zu überschreiben, die diese Schnittstelle erweitert?

Das Beispiel:

Wahrscheinlich mache ich etwas falsch, aber hier ist, was ich habe:

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

Normalerweise kann man in PHP, wenn man etwas erweitert, jede darin enthaltene Methode überschreiben (richtig?). Wenn jedoch eine Schnittstelle eine andere erweitert, lässt sie das nicht zu. Es sei denn, ich sehe das falsch... Wenn ich die Schnittstelle iShipper implementiere, muss ich nicht dafür sorgen, dass das Shipper-Objekt das Vendor-Objekt (das die Schnittstelle iVendor implementiert) erweitert. Ich sage einfach:

class FedEx implements iShipper{}

und FedEx alle Methoden von iVendor und iShipper implementieren lassen. Ich brauche jedoch die __construct Funktionen in iVendor und iShipper müssen eindeutig sein. Ich weiß, ich könnte die $shipment = null aber dann wäre es nicht mehr so bequem, Shipper zu erstellen (indem man beim Instanzieren einfach die vendors_no und die Sendung angibt).

Weiß jemand, wie das funktionieren kann? Mein Ausweg ist, dass ich die Sendung durch den Aufruf von $shipper->setShipment($shipment); auf den Shipper, nachdem ich es instanziieren, aber ich hoffe für einen Weg, um zu umgehen, dass zu tun...

Für die Neugierigen noch eine kleine Erklärung:
Das FedEx-Objekt verfügt über Methoden, die auf die FedEx-Website gehen (mit cURL) und einen Kostenvoranschlag für die betreffende Sendung erhalten. Ich habe ein UPS Objekt, ein BAXGlobal Objekt, ein Conway Objekt, etc. Jedes hat VÖLLIG unterschiedliche Methoden, um den Kostenvoranschlag für den Versand zu erhalten, aber alles, was das System wissen muss, ist, dass es sich um einen "Versender" handelt und dass die in der Schnittstelle aufgelisteten Methoden für sie aufrufbar sind (so dass es sie alle genau gleich behandeln und in einer Schleife durch sie in einem "Versender"-Array aufrufen kann getTransitX() um den besten Versender für eine Sendung zu finden).

Jeder "Versender" ist jedoch auch ein "Lieferant" und wird in anderen Teilen des Systems als solcher behandelt (Abrufen und Einstellen in die DB usw.). Unser Datendesign ist ein Haufen Mist, so dass FedEx direkt neben Unternehmen wie Dunder Mifflin in der Tabelle "Vendoren" gespeichert ist, was bedeutet, dass es alle Eigenschaften jedes anderen Anbieters hat, aber die zusätzlichen Eigenschaften und Methoden benötigt, die von iShipper bereitgestellt werden).

6voto

Ryan Ahearn Punkte 7766

@cmcculloh Ja, in Java definiert man keine Konstruktoren in Interfaces. Dadurch können Sie sowohl Schnittstellen erweitern als auch eine Klasse haben, die mehrere Schnittstellen implementiert (beides ist erlaubt und in vielen Fällen sehr nützlich), ohne sich Gedanken darüber zu machen, dass Sie einen bestimmten Konstruktor erfüllen müssen.

EDIT:

Hier ist mein neues Modell:

A. Jede Schnittstelle verfügt nicht mehr über eine Konstruktormethode.
B. Alle Versender (UPS, FedEx usw.) implementieren jetzt iShipper (das iVendor erweitert) und erweitern die abstrakte Klasse Shipper (in der alle gängigen nicht-abstrakten Methoden für Versender definiert sind, getName(), getZip() usw.).
C. Jeder Shipper hat seine eigene einzigartige _construct-Methode, die die abstrakte __construct($vendors_no = null, $shipment = null)-Methode im Shipper überschreibt (ich weiß nicht mehr, warum ich diese jetzt optional zulasse. Ich müsste meine Dokumentation noch einmal durchgehen...).

Also:

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

Vielen Dank für die Hilfe!
ps. da ich dies nun zu "Ihrer" Antwort hinzugefügt habe, können Sie es gerne ändern, wenn Ihnen etwas daran nicht gefällt oder Sie denken, dass es anders sein sollte...

0voto

mk. Punkte 25456

Man könnte den Konstruktor weglassen und sie einfach in jede einzelne Klasse einfügen. Dann hat jede Klasse ihr eigenes __construct, das wahrscheinlich dasselbe ist, je nachdem, ob es sich um einen Verlader oder Verkäufer handelt. Wenn Sie diese Konstrukte nur einmal definiert haben wollen, glaube ich nicht, dass Sie diesen Weg gehen wollen.

Ich denke, Sie möchten eine abstrakte Klasse erstellen, die vendor implementiert, und eine, die shipper implementiert. Dort könnten Sie die Konstruktoren unterschiedlich definieren.

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

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

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X