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:
O "problema do diamante" (às vezes chamado de "diamante mortal da morte") é uma ambiguidade que surge quando duas classes B e C herdam de A e a classe D herda de B e C. Se houver um método em A que B e C substituíram e D não o substituiu; então, qual versão do método D herda: a de B ou a de C?
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).
// Methods inside this interface must be implemented in all classes which implement this interface.
interface IPersonService
{
public function Create($personObject);
}
class MySqlPerson implements IPersonService
{
public function Create($personObject)
{
// Create a new person in MySql database.
}
}
class MongoPerson implements IPersonService
{
public function Create($personObject)
{
// Mongo database creates a new person differently then MySQL does. But the code outside of this method doesn't care how a person will be added to the database, all it has to know is that the method Create() has 1 parameter (the person object).
}
}
Dessa forma, o Create()
método sempre será usado da mesma maneira. Não importa se estamos usando a MySqlPerson
classe ou a MongoPerson
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):
new MySqlPerson()->Create($personObject);
new MongoPerson()->Create($personObject);
Dessa forma, algo assim não pode acontecer:
new MySqlPerson()->Create($personObject)
new MongoPerson()->Create($personsName, $personsAge);
É 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étodo Create()
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 a IPersonService
interface terá o método Create()
(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.