¿Por qué necesitarías una interfaz, si ya hay clases abstractas?
Para evitar la herencia múltiple (puede causar múltiples problemas conocidos).
Uno de esos problemas:
El "problema del diamante" (a veces denominado "diamante mortal de la muerte") es una ambigüedad que surge cuando dos clases B y C heredan de A y la clase D hereda de B y C. Si hay un método en A que B y C se han anulado, y D no lo anula, entonces, ¿qué versión del método hereda D: la de B o la de C?
Fuente: https://en.wikipedia.org/wiki/Multiple_inheritance#The_diamond_problem
¿Por qué / cuándo usar una interfaz?
Un ejemplo ... Todos los autos en el mundo tienen la misma interfaz (métodos) ... AccelerationPedalIsOnTheRight()
, BrakePedalISOnTheLeft()
. Imagine que cada marca de automóvil tendría estos "métodos" diferentes de otra marca. BMW tendría los frenos en el lado derecho, y Honda tendría frenos en el lado izquierdo del volante. Las personas tendrían que aprender cómo funcionan estos "métodos" cada vez que comprarían una marca de automóviles diferente. Por eso es una buena idea tener la misma interfaz en múltiples "lugares".
¿Qué hace una interfaz por usted (por qué alguien usaría una)? Una interfaz le impide cometer "errores" (le asegura que todas las clases que implementan una interfaz específica tendrán todos los métodos que están en la interfaz).
// 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).
}
}
De esta manera, el Create()
método siempre se utilizará de la misma manera. No importa si estamos usando la MySqlPerson
clase o la MongoPerson
clase. La forma en que estamos utilizando un método permanece igual (la interfaz sigue siendo la misma).
Por ejemplo, se usará así (en todas partes en nuestro código):
new MySqlPerson()->Create($personObject);
new MongoPerson()->Create($personObject);
De esta manera, algo como esto no puede suceder:
new MySqlPerson()->Create($personObject)
new MongoPerson()->Create($personsName, $personsAge);
Es mucho más fácil recordar una interfaz y usar la misma en todas partes, que múltiples diferentes.
De esta manera, el interior del Create()
método puede ser diferente para diferentes clases, sin afectar el código "externo", que llama a este método. Todo lo que el código externo tiene que saber es que el método Create()
tiene 1 parámetro ( $personObject
), porque así es como el código externo usará / llamará al método. Al código externo no le importa lo que sucede dentro del método; solo tiene que saber cómo usarlo / llamarlo.
También puede hacer esto sin una interfaz, pero si usa una interfaz, es "más segura" (porque evita que cometa errores). La interfaz le asegura que el método Create()
tendrá la misma firma (los mismos tipos y el mismo número de parámetros) en todas las clases que implementan la interfaz. De esta manera, puede estar seguro de que CUALQUIER clase que implemente la IPersonService
interfaz tendrá el método Create()
(en este ejemplo) y solo necesitará 1 parámetro ( $personObject
) para ser llamado / utilizado.
Una clase que implementa una interfaz debe implementar todos los métodos, que la interfaz hace / tiene.
Espero no haberme repetido demasiado.