Pergunta

Existe uma maneira no PHP de sobrescrever um método declarado por uma interface em uma interface que estende essa interface?

O exemplo:

Provavelmente estou fazendo algo errado, mas aqui está o que tenho:

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

Normalmente em PHP, quando você estende algo, você pode sobrescrever qualquer método contido nele (certo?).No entanto, quando uma interface estende outra, isso não permitirá.A menos que eu esteja pensando nisso errado...Quando implemento a interface iShipper, não preciso fazer com que o objeto Shipper estenda o objeto Vendor (que implementa a interface iVendor).Eu só digo:

class FedEx implements iShipper{}

e fazer com que a FedEx implemente todos os métodos do iVendor e do iShipper.No entanto, preciso do __construct funções no iVendor e iShipper sejam únicas.Eu sei que poderia tirar o $shipment = null, mas não seria tão conveniente criar Remetentes (apenas passando o vendors_no e a remessa durante a instanciação).

Alguém sabe como fazer isso funcionar?Minha alternativa é ter que definir a remessa ligando para $shipper->setShipment($shipment); no remetente depois de instanciá-lo, mas espero encontrar uma maneira de contornar a necessidade de fazer isso ...

Um pouco mais de explicação para os curiosos:
O Objeto FedEx possui métodos que acessam o site da FedEx (usando cURL) e obtêm uma estimativa para a Remessa em questão.Eu tenho um objeto UPS, um objeto BAXGlobal, um objeto Conway, etc.Cada um tem métodos COMPLETAMENTE diferentes para obter a estimativa de envio, mas tudo o que o sistema precisa saber é que eles são um "remetente" e que os métodos listados na interface podem ser chamados por eles (para que possa tratá-los todos exatamente da mesma forma). , e percorrê-los em uma matriz "shippers" chamando getTransitX() para encontrar o melhor remetente para uma remessa).

Cada "Remetente" também é um "Fornecedor" e é tratado como tal em outras partes do sistema (obter e colocar no banco de dados, etc.Nosso design de dados é uma porcaria, então a FedEx é armazenada ao lado de empresas como Dunder Mifflin na tabela "Fornecedores", o que significa que ela terá todas as propriedades de todos os outros fornecedores, mas precisa das propriedades e métodos extras fornecidos pelo iShipper ).

Foi útil?

Solução

@cmculloh Sim, em Java você não define construtores em Interfaces.Isso permite estender interfaces e também ter uma classe que implementa múltiplas interfaces (ambas permitidas e muito úteis em muitos casos) sem se preocupar em ter que satisfazer um construtor específico.

EDITAR:

Aqui está meu novo modelo:

A.Cada interface não possui mais um método construtor.
B.Todos os expedidores (UPS, FedEx, etc) agora implementam o iShipper (que estende o iVendor) e estendem a classe abstrata Shipper (que possui todos os métodos não abstratos comuns para expedidores definidos nele, getName(), getZip() etc).
C.Cada Shipper tem seu próprio método _construct exclusivo que substitui o método abstrato __construct($vendors_no = null, $shipment = null) contido no Shipper (não me lembro por que estou permitindo que eles sejam opcionais agora.Eu teria que voltar na minha documentação...).

Então:

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

Obrigado pela ajuda!
obs.já que adicionei isso à "sua" resposta, se houver algo que você não gosta/acha que deveria ser diferente, sinta-se à vontade para alterá-lo ...

Outras dicas

Você poderia abandonar o construtor e simplesmente colocá-los em cada classe individual.Então o que você tem é que cada classe tem seu próprio __construct, que provavelmente é o mesmo dependendo se é um remetente ou fornecedor.Se você deseja definir essas construções apenas uma vez, não acho que você queira seguir esse caminho.

O que eu acho que você quer fazer é criar uma classe abstrata que implemente o fornecedor e outra que implemente o remetente.Lá você poderia definir os construtores de forma diferente.

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

abstract class Shipper implements iShipper {
    public function __construct() {
        something();
    }
}
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top