As interfaces permitem criar código que define os métodos das classes que o implementam. No entanto, você não pode adicionar nenhum código a esses métodos.
As classes abstratas permitem que você faça a mesma coisa, além de adicionar código ao método.
Agora, se você pode alcançar o mesmo objetivo com as classes abstratas, por que precisamos do conceito de interfaces?
Foi-me dito que isso tem a ver com a teoria de OO, de C ++ a Java, que é o material do PHP baseado em OO. O conceito é útil em Java, mas não em PHP? É apenas uma maneira de evitar que os espaços reservados sejam desarrumados na classe abstrata? Estou esquecendo de algo?
Respostas:
O objetivo das interfaces é oferecer a flexibilidade de que sua classe seja forçada a implementar várias interfaces, mas ainda não permita herança múltipla. Os problemas com a herança de várias classes são muitos e variados, e a página da Wikipedia nela os resume muito bem.
As interfaces são um compromisso. A maioria dos problemas com herança múltipla não se aplica a classes base abstratas, portanto, a maioria das linguagens modernas hoje em dia desabilita a herança múltipla, mas ainda chama interfaces de classes base abstratas e permite que uma classe "implemente" quantas delas quiser.
fonte
O conceito é útil em toda a programação orientada a objetos. Para mim, penso em uma interface como um contrato. Desde que minha turma e sua turma concordem com este contrato de assinatura de método, podemos "fazer interface". Quanto às classes abstratas, aquelas que eu vejo como mais classes básicas que esboçam alguns métodos e preciso preencher os detalhes.
fonte
Por que você precisaria de uma interface, se já existem classes abstratas? Para impedir a herança múltipla (pode causar vários problemas conhecidos).
Um desses problemas:
Fonte: https://en.wikipedia.org/wiki/Multiple_inheritance#The_diamond_problem
Por que / quando usar uma interface? Um exemplo ... Todos os carros no mundo têm a mesma interface (métodos) ...
AccelerationPedalIsOnTheRight()
,BrakePedalISOnTheLeft()
. Imagine que cada marca de carro tenha esses "métodos" diferentes de outra marca. BMW teria os freios no lado direito, e Honda teria freios no lado esquerdo da roda. As pessoas precisariam aprender como esses "métodos" funcionam toda vez que comprariam uma marca diferente de carro. É por isso que é uma boa ideia ter a mesma interface em vários "lugares".O que uma interface faz por você (por que alguém usaria uma)? Uma interface evita que você cometa "erros" (assegura que todas as classes que implementam uma interface específica terão todos os métodos que estão na interface).
Dessa forma, o
Create()
método sempre será usado da mesma maneira. Não importa se estamos usando aMySqlPerson
classe ou aMongoPerson
classe. A maneira como estamos usando um método permanece a mesma (a interface permanece a mesma).Por exemplo, será usado assim (em qualquer lugar do nosso código):
Dessa forma, algo assim não pode acontecer:
É muito mais fácil lembrar de uma interface e usar a mesma em todos os lugares, do que várias diferentes.
Dessa forma, o interior do
Create()
método pode ser diferente para diferentes classes, sem afetar o código "externo", que chama esse método. Tudo o que o código externo precisa saber é que o métodoCreate()
possui 1 parâmetro ($personObject
), porque é assim que o código externo usa / chama o método. O código externo não se importa com o que está acontecendo dentro do método; ele só precisa saber como usá-lo / chamá-lo.Você pode fazer isso sem uma interface também, mas se você usar uma interface, é "mais seguro" (porque impede que você cometa erros). A interface garante que o método
Create()
tenha a mesma assinatura (mesmos tipos e um mesmo número de parâmetros) em todas as classes que implementam a interface. Dessa forma, você pode ter certeza de que QUALQUER classe que implementa aIPersonService
interface terá o métodoCreate()
(neste exemplo) e precisará de apenas 1 parâmetro ($personObject
) para ser chamado / usado.Uma classe que implementa uma interface deve implementar todos os métodos que a interface possui / possui.
Espero não ter me repetido demais.
fonte
A diferença entre usar uma interface e uma classe abstrata tem mais a ver com a organização do código do que com a aplicação pela própria linguagem. Eu os uso muito ao preparar o código para outros desenvolvedores trabalharem, para que eles permaneçam dentro dos padrões de design pretendidos. As interfaces são um tipo de "design por contrato", no qual seu código concorda em responder a um conjunto prescrito de chamadas de API que podem ser provenientes de códigos que você não aceita.
Embora a herança da classe abstrata seja uma relação "é uma", isso nem sempre é o que você deseja, e implementar uma interface é mais uma relação "age como uma". Essa diferença pode ser bastante significativa em certos contextos.
Por exemplo, digamos que você tenha uma conta de classe abstrata da qual muitas outras classes se estendem (tipos de contas e assim por diante). Ele tem um conjunto específico de métodos que são aplicáveis apenas a esse grupo de tipos. No entanto, algumas dessas subclasses de conta implementam Versionable, Listable ou Editable, para que possam ser lançadas em controladores que esperam usar essas APIs. O controlador não se importa com o tipo de objeto.
Por outro lado, também posso criar um objeto que não se estenda da Conta, digamos uma classe abstrata Usuário, e ainda implemente Listável e Editável, mas não Versão, o que não faz sentido aqui.
Dessa forma, estou dizendo que a subclasse FooUser NÃO é uma conta, mas age como um objeto Editável. Da mesma forma, BarAccount se estende da Conta, mas não é uma subclasse de Usuário, mas implementa Editável, Listável e também Versão.
A adição de todas essas APIs para Editável, Listável e Versionável nas próprias classes abstratas não seria apenas desorganizada e feia, mas duplicaria as interfaces comuns em Conta e Usuário ou forçaria meu objeto Usuário a implementar o Versionável, provavelmente apenas para lançar um exceção.
fonte
As interfaces são essencialmente um modelo para o que você pode criar. Eles definem quais métodos uma classe deve ter , mas você pode criar métodos extras fora dessas limitações.
Não sei ao certo o que você quer dizer com não poder adicionar código aos métodos - porque você pode. Você está aplicando a interface a uma classe abstrata ou à classe que a estende?
Um método na interface aplicada à classe abstrata precisará ser implementado nessa classe abstrata. No entanto, aplique essa interface à classe de extensão e o método só precisa ser implementado na classe de extensão. Eu posso estar errado aqui - não uso interfaces com a frequência que poderia / deveria.
Eu sempre pensei nas interfaces como um padrão para desenvolvedores externos ou um conjunto de regras extra para garantir que as coisas estejam corretas.
fonte
Você usará interfaces no PHP:
$object instanceof MyInterface
Car
objeto ca agorastart()
,stop()
(EngineInterface) ougoRight()
,goLeft()
(interface de direção)e outras coisas em que não consigo pensar agora
Número 4, é provavelmente o caso de uso mais óbvio que você não pode resolver com classes abstratas.
De Pensando em Java:
fonte
As interfaces existem não como uma base na qual as classes podem se estender, mas como um mapa das funções necessárias.
A seguir, é apresentado um exemplo do uso de uma interface em que uma classe abstrata não se encaixa:
Digamos que eu tenha um aplicativo de calendário que permita aos usuários importar dados de calendário de fontes externas. Eu escreveria classes para lidar com a importação de cada tipo de fonte de dados (ical, rss, atom, json). Cada uma dessas classes implementaria uma interface comum que garantiria que todos eles tivessem os métodos públicos comuns que meu aplicativo precisa para obter os dados.
Então, quando um usuário adiciona um novo feed, posso identificar o tipo de feed e usar a classe desenvolvida para esse tipo para importar os dados. Cada classe gravada para importar dados para um feed específico teria código completamente diferente. Caso contrário, poderá haver muito poucas semelhanças entre as classes, exceto pelo fato de serem necessárias para implementar a interface que permite que meu aplicativo as consuma. Se eu usasse uma classe abstrata, poderia facilmente ignorar o fato de não ter substituído o método getEvents () que quebraria meu aplicativo nessa instância, enquanto o uso de uma interface não deixaria meu aplicativo executar se QUALQUER um dos métodos definido na interface não existe na classe que o implementou. Meu aplicativo não precisa se importar com a classe usada para obter dados de um feed,
Para dar um passo adiante, a interface se mostra extremamente útil quando eu voltar ao meu aplicativo de calendário com a intenção de adicionar outro tipo de feed. Usar a interface ImportableFeed significa que posso continuar adicionando mais classes que importam diferentes tipos de feed, simplesmente adicionando novas classes que implementam essa interface. Isso permite que eu adicione toneladas de funcionalidade sem ter que adicionar desnecessariamente em massa ao meu aplicativo principal, já que meu aplicativo principal depende apenas da existência de métodos públicos disponíveis que a interface exige, desde que minhas novas classes de importação de feed implementem a interface ImportableFeed. sei que posso simplesmente colocá-lo no lugar e seguir em frente.
Este é apenas um começo muito simples. Posso então criar outra interface que todas as minhas classes de calendário possam implementar, oferecendo mais funcionalidades específicas ao tipo de feed que a classe manipula. Outro bom exemplo seria um método para verificar o tipo de feed etc.
Isso vai além da questão, mas desde que eu usei o exemplo acima: As interfaces vêm com seu próprio conjunto de problemas, se usadas dessa maneira. Sinto-me precisando garantir a saída retornada dos métodos implementados para corresponder à interface e, para isso, utilizo um IDE que lê blocos PHPDoc e adiciono o tipo de retorno como uma dica de tipo em um bloco PHPDoc da interface que, em seguida, traduzir para a classe concreta que a implementa. Minhas classes que consomem a saída de dados das classes que implementam essa interface, no mínimo, sabem que estão esperando uma matriz retornada neste exemplo:
Não há muito espaço para comparar classes e interfaces abstratas. Interfaces são simplesmente mapas que, quando implementados, exigem que a classe tenha um conjunto de interfaces públicas.
fonte
As interfaces não servem apenas para garantir que os desenvolvedores implementem certos métodos. A idéia é que, como é garantido que essas classes tenham certos métodos, você pode usá-los mesmo que não conheça o tipo real da classe. Exemplo:
Em muitos casos, não faz sentido fornecer uma classe base, abstrata ou não, porque as implementações variam muito e não compartilham nada em comum além de alguns métodos.
Linguagens dinamicamente tipadas têm a noção de "digitação de pato", na qual você não precisa de interfaces; você pode assumir que o objeto tem o método que você está chamando. Isso soluciona o problema em linguagens estaticamente tipadas em que seu objeto tem algum método (no meu exemplo, read ()), mas não implementa a interface.
fonte
Na minha opinião, as interfaces devem ser preferidas às classes abstratas não funcionais. Eu não ficaria surpreso se houvesse um impacto no desempenho, pois há apenas um objeto instanciado, em vez de analisar dois, combinando-os (embora, não tenha certeza, não estou familiarizado com o funcionamento interno OOP PHP).
É verdade que as interfaces são menos úteis / significativas do que em comparação com, digamos, Java. Por outro lado, o PHP6 apresentará ainda mais dicas de tipo, incluindo dicas de tipo para valores de retorno. Isso deve adicionar algum valor às interfaces PHP.
tl; dr: interfaces define uma lista de métodos que precisam ser seguidos (pense na API), enquanto uma classe abstrata fornece algumas funcionalidades básicas / comuns, que as subclasses refinam para necessidades específicas.
fonte
No PHP, você pode aplicar várias interfaces, separando-as com uma vírgula (acho que não considero uma solução limpa).
Quanto a várias classes abstratas, você pode ter vários resumos se estendendo (novamente, não tenho muita certeza disso, mas acho que já vi isso em algum lugar antes). A única coisa que você não pode estender é uma aula final.
fonte
As interfaces não fornecerão ao seu código nenhum aumento de desempenho ou algo parecido, mas podem ajudar bastante a torná-lo sustentável. É verdade que uma classe abstrata (ou mesmo uma classe não abstrata) pode ser usada para estabelecer uma interface para o seu código, mas as interfaces apropriadas (aquelas que você define com a palavra-chave e que contêm apenas assinaturas de método) são muito mais fáceis de usar. classificar e ler.
Dito isto, costumo usar discrição ao decidir se deve ou não usar uma interface em uma classe. Às vezes, eu quero implementações de métodos padrão ou variáveis que serão comuns a todas as subclasses.
Obviamente, a questão da implementação de múltiplas interfaces também é sólida. Se você possui uma classe que implementa várias interfaces, pode usar um objeto dessa classe como tipos diferentes no mesmo aplicativo.
O fato de sua pergunta ser sobre PHP, no entanto, torna as coisas um pouco mais interessantes. Digitar nas interfaces ainda não é incrivelmente necessário no PHP, onde você pode praticamente alimentar qualquer coisa com qualquer método, independentemente do seu tipo. Você pode digitar estaticamente os parâmetros do método, mas alguns deles estão quebrados (String, acredito, causa alguns soluços). Junte isso ao fato de que você não pode digitar a maioria das outras referências e não há muito valor em tentar forçar a digitação estática no PHP ( neste momento ). E por isso, o valor das interfaces no PHP , neste momentoé muito menor do que em idiomas mais fortemente tipados. Eles têm o benefício da legibilidade, mas pouco mais. A implementação múltipla nem é benéfica, porque você ainda precisa declarar os métodos e fornecer a eles corpos dentro do implementador.
fonte
Abaixo estão os pontos para a interface PHP
Código de exemplo:
fonte
Vimos que classes e interfaces abstratas são semelhantes, pois fornecem métodos abstratos que devem ser implementados nas classes filho. No entanto, eles ainda têm as seguintes diferenças:
Espero que isso ajude alguém a entender!
fonte
As interfaces são como seus genes.
As aulas abstratas são como seus pais de verdade.
Seus propósitos são hereditários, mas no caso de classes abstratas versus interfaces, o que é herdado é mais específico.
fonte
Eu não sei sobre outras línguas, qual é o conceito de interface lá. Mas para o PHP, tentarei o meu melhor para explicá-lo. Apenas seja paciente e, por favor, comente se isso ajudou.
A regra
Agora vamos dar um exemplo. Suponha que tenhamos dois brinquedos: um é um cachorro e o outro é um gato.
Como sabemos, um cão late e miadeiros. Esses dois têm o mesmo método de fala, mas com funcionalidade ou implementação diferente. Suponha que estamos dando ao usuário um controle remoto que possui um botão de falar.
Este é um bom caso para usar uma interface, não uma classe abstrata, porque as implementações são diferentes. Por quê? Lembrar
Se você precisar dar suporte às classes filho adicionando algum método não abstrato, use classes abstratas. Caso contrário, as interfaces seriam sua escolha.
fonte