¿Por qué PHP tiene interfaces?


35

Noté que a partir de PHP5, se han agregado interfaces al lenguaje. Sin embargo, dado que PHP está tan tipado, parece que se pierden la mayoría de los beneficios del uso de interfaces. ¿Por qué se incluye esto en el idioma?


55
Creo que la pregunta correcta es, ¿por qué no?
Alberto Fernández

55
porque no parecen ofrecer ningún beneficio, entonces ¿por qué incluirlos?
GSto

44
@HorusKol y antes de que se implementaran, no se usaban, por lo que puede ver cómo no se usaron e inutilizaron solo una versión anterior. También debe hacer y respaldar la afirmación de que su uso es de alguna manera una mejora para decir que son útiles.
Rein Henrichs

66
@HorusKol No es engañoso en absoluto. Es fácil demostrar la propuesta de valor del martillo. Esta pregunta es pedirle a alguien que demuestre la propuesta de valor de las interfaces PHP, no solo que declare que son valiosas de manera argumentativa.
Rein Henrichs

3
Y recuerde que las interfaces no son solo para escribir. Una interfaz es un contrato que establece que una clase de implementación debe incluir los métodos que establece. Útil para cosas como los motores de complementos.
Michael

Respuestas:


30

La principal ventaja de las interfaces en PHP es que las clases pueden implementar múltiples interfaces. Esto le permite agrupar clases que comparten alguna funcionalidad pero que no necesariamente comparten una clase principal. Algunos ejemplos pueden incluir el almacenamiento en caché, la salida o el acceso a las propiedades de la clase de cierta manera.

En su código, puede verificar si una clase implementa una interfaz dada en lugar de verificar el nombre de la clase. Entonces, su código seguirá funcionando cuando se agreguen nuevas clases.

PHP proporciona algunas interfaces predefinidas que pueden ser útiles en diversas situaciones: http://php.net/manual/en/reserved.interfaces.php .

EDITAR - Agregar un ejemplo

Si tiene una interfaz llamada MyInterface y está trabajando con varios objetos de diferentes clases que pueden o no compartir alguna funcionalidad, las interfaces le permiten hacer algo como esto:

// Assume $objects is an array of instances of various classes
foreach($objects as $obj) {
 if($obj instanceof MyInterface) {
     $obj->a();
     $obj->b();
     $obj->c();
   }
}

23
En otras palabras: "puedes ignorar por completo todos los beneficios de los lenguajes de tipo dinámico"
Kamil Tomšík

11
@Kamil, creo que es más como aprovechar los beneficios de la escritura estática sin sufrir los inconvenientes cuando no los quieres.
Karl Bielefeldt

99
¿En serio? ¿en vez de? if-then-if-then-if-then-all-the-time, ¿no te suena familiar? ah, sí, programación de procedimientos.
Kamil Tomšík

23
@Kamil Tomšík Otro insulto al lenguaje de PHP en lugar de las personas que lo usan de manera incompetente. PHP tiene todas las herramientas para una programación completa orientada a objetos. Si los usa o no, depende del programador. Además, no hay nada de malo en la programación de procedimientos en sí misma.
Lotus Notes

18
@Kamil: qué extraño, al leer tu comentario, uno podría llegar a la conclusión de que no hay "s" en la OOP y que, de alguna manera, mágicamente, las cosas funcionan. Guau.
Michael JV

23

PHP se tipea libremente, pero se puede tipear fuertemente sobre cosas como parámetros de métodos.

Considere el siguiente ejemplo:

interface Car { function go(); }

class Porsche { function go() {} }

function drive(Car $car) {}

$porsche = new Porsche();

drive($porsche);

El código anterior generaría:

El argumento 1 pasado a drive () debe implementar la interfaz Car, instancia de Porsche dada


1
Claro que es muy malo. Sin nullembargo, puede tener un valor predeterminado para el parámetro.
Emanuil Rusev

55
pero si driverequiere una Car, pasando luego nullno sería de todas formas muy útiles ...
HorusKol

77
Nunca pase nulo. Utilice un objeto "Caso especial" (Google para la explicación de Martin Fowler).
Martin Blore

2
@Renesis Si establece el valor predeterminado en nulo, puede pasar nulo a los métodos de tipo insinuado. (CAR $ car = null) le permitiría llamar a este método con nulo como argumento. Sin embargo, esta sería una práctica bastante tonta. ¿Por qué querrías poder hacer eso?
dqhendricks

2
Ejemplo concreto: function addView($name, Template $template, SecurityMode $securityMode = null, $methodName = null);puede que tengas un $methodNamepero no $securityMode.
Nicole

7

Las interfaces le permiten implementar el principio abierto-cerrado, mantener una base de código débilmente acoplada e implementar muchos de los mejores patrones de diseño de OOP.

Por ejemplo, si una clase acepta otra clase como argumento:

class A {

    public function __construct(B $class_b) {
        // use class b
        $class_b->run();
    }
}

Su clase A y clase B ahora tienen un acoplamiento estrecho, y la clase A no puede usar ninguna otra clase excepto B. La sugerencia de tipo asegura que tenga el tipo correcto de argumento, pero ahora ha consolidado la relación entre A y B.

Sin embargo, digamos que desea que la clase A pueda usar todos los tipos de clases que tienen un método run (). Esto es básicamente (pero no del todo) el patrón de diseño de COMANDO. Para resolverlo, en su lugar, escribiría una sugerencia utilizando una interfaz en lugar de una clase concreta. B implementarían esa interfaz y serán aceptados como argumento para la clase A. De esta manera, la clase A puede aceptar cualquier clase que use esa interfaz como argumento para su constructor.

Este tipo de codificación se usa en la mayoría de los patrones de diseño de OOP, y permite cambios MUCHO más fáciles de código en un momento posterior. Estos son parte de los fundamentos de la programación de AGILE.


1
O cualquier subclase de B
Mez

7

@pjskeptic tiene una buena respuesta , y @Kamil Tomšík tiene un buen comentario sobre esa respuesta.

Lo mejor de los lenguajes de tipo dinámico como PHP es que puedes intentar usar métodos en objetos y no te gritará a menos que el método no esté allí.

El problema con los lenguajes de tipo dinámico como PHP es que puedes intentar usar métodos en objetos y te gritará cuando el método no esté allí.

Las interfaces agregan una forma conveniente de invocar métodos en un objeto desconocido y asegurarse de que los métodos están allí (no es que sean necesariamente correctos o vayan a funcionar). No es una parte necesaria de un lenguaje, pero hace que la codificación sea más conveniente. Permite a los desarrolladores de OOP fuertemente tipados escribir código PHP fuertemente tipado, que luego puede funcionar junto con el código PHP tipeado libremente escrito por un desarrollador PHP diferente.

una función como:

foo( IBar $bar )
{
  $baz = $bar->baz();
  ...
}

es más conveniente que:

foo( $bar )
{
  if ( method_exists( $bar, 'baz' ) )
  {
    $baz = $bar->baz();
  }
  else
  {
    throw new Exception('OMGWTF NO BAZ IN BAR!');
  }
  ...
}

y en mi humilde opinión, el código simple y legible es mejor código.


1
lo que haces en su lugar es simplemente no verificar el método y bloquearse y quemarse cuando alguien llama a tu función con los datos incorrectos. No es tu problema si alguien usa mal tu función.
Raynos

no exactamente - tu ejemplo es la pesadilla para cualquier persona que quiera pasar cualquier "pato" dinámico, como proxy, adaptador, etc. decorador
Kamil Tomsik

1
@Kamil? Cómo es eso. Un proxy sería una clase de contenedor para algo que no implementa la interfaz para permitir que se use con esta función.
tylermac

@tylermac proxy dinámico usando __call () - y si __call es el único método allí, simplemente no puede implementar IBar, lo que significa que no puede pasarlo a foo (IBar $ bar)
Kamil Tomšík

5

Son completamente inútiles si eres tipeador de patos, en realidad cuando escribes patos, es bastante molesto trabajar con bibliotecas / framework que usan cualquier tipo de sugerencia.

Esto también se aplica a todo tipo de metaprogramación dinámica (métodos mágicos).


3

PHP no es suelto o fuerte, sino que se escribe dinámicamente .

Acerca de las interfaces, lo primero que debe preguntarse es: ¿cuáles son la mayoría de los beneficios de las interfaces?

En OOP, las interfaces no son solo sobre tipos, sino también sobre el comportamiento.

Dado que PHP también tiene una función de sugerencia de tipo , puede usar interfaces como lo haría en un lenguaje puro, como Java.

interface File
{
    public function getLines();
}

CSVFile implements File
{
    public function getLines()
    {}
}

XMLFile implements File 
{
    public function getLines()
    {}
}

JSONFile implements File 
{
    public function getLines()
    {}
}

class FileReader
{
    public function read(File $file)
    {
        foreach($file->getLines() as $line)
        {
            // do something
        }
    }
}

Con la implementación de la interfaz PHP, también puede crear simulacros para clases abstractas utilizando PHPUnit , y esta es una característica increíble:

public function testSomething()
{
    $mock = $this->getMockForAbstractClass('File');

    $mock->expects($this->once())
         ->method('getLines')
         ->will($this->returnValue(array()));

    // do your assertions
}

Entonces, básicamente, puede tener una aplicación SOLID compatible en PHP utilizando las características del lenguaje, una de ellas son las interfaces.


0

Las interfaces son útiles para la inyección de dependencias mucho más que el concreto. Como un ejemplo básico:

interface Istore { 
  public function save(); 
}

class Article_DB implements Istore 
{ 
  public function save($data) 
  {
    // do save to format needed.
  } 
}

class Article
{
   private $content;

   public function content($content)
   {
     $this->content = $content;
   }

   public function save(Istore $store)
   {
     $store->save($this->content);
   }
}

$article = new Article();
$article->content('Some content');

$store = new Article_DB();
$article->save($store);

Ahora diga si sus necesidades cambian y desea guardar en un pdf. Podría crear una nueva clase para ese propósito en lugar de contaminar la clase Artículo.

class Article_PDF implements Istore 
{ 
  public function save($data) 
  {
    // do save to format needed.
  } 
}


$article = new Article();
$article->content('Some content');

$store = new Article_PDF();
$article->save($store);

La clase Artículo ahora tiene un contrato que las clases que usa para guardar deben implementar la interfaz Istore. No le importa dónde ahorra ni cómo ahorra.


-1

Puede proporcionar objetos reales "falsos" que implementen la interfaz. Luego, puede probar una parte de su código sin requerir servidores, sistemas de archivos, sockets, bases de datos, etc.


-3

Mucha gente probablemente me odiará por responder de esta manera, pero la solución a sus problemas de escritura se puede solucionar fácilmente con PHP. Sí, PHP está tipeado de manera flexible, por lo que se asumen los tipos de forma predeterminada, lo que puede causar algunos problemas, especialmente en las operaciones de comparación, que es el problema de la mayoría de las personas con él. Dicho esto, PHP puede ser tan estricto como cualquier lenguaje fuertemente tipado si convierte lo que está utilizando en el tipo que necesita, y luego usa operadores de comparación bit a bit. Este es el ejemplo más fácil que puedo pensar de lo que estoy diciendo:

$ myVar = (int) 0; $ myOtherVar = '0';

comparar ($ myVar == $ myVar) sería igual (bool) verdadero

pero comparar ($ myVar === $ myVar) sería igual (bool) falso al igual que cualquier comparación "escrita"

Realmente desearía que los desarrolladores dejaran de discutir sobre estas cosas, si tienes un problema con la forma en que funciona PHP, ve al programa en Java y vive y deja vivir, o úsalo de la forma en que hará lo que quieras. ¿Qué bien te hace quejarse de eso de todos modos? ¿Te das una excusa para joder todo el día? ¿Te hace ver mejor que alguien más? Bueno, es genial que te sientas tan bien contigo mismo que estés dispuesto a hacer que alguien más se vea mal, pero en realidad es tu preferencia y forzar tus creencias sobre cualquiera realmente los hace codificar de una manera que no se sienten cómodos causando tres cosas:

1) Codificarán su camino pero "desordenado" según sus estándares (piense, ¿alguna vez ha visto a un programador de Java crear su primer programa PHP o viceversa? Será de la misma manera cambiando su metodología o incluso peor).

2) Encontrarás algo más por lo que quejarte

3) Probablemente les tomará más tiempo producir. Y tal vez lo hará verse mejor a corto plazo, pero el equipo en su conjunto lo verá peor (recuerde que puede codificar más lentamente que otra persona y eso no es necesariamente malo siempre que el equipo cumpla con los entregables en un plazo razonable, pero forzar sus hábitos a alguien que generalmente se ha desempeñado un poco más rápido puede terminar haciendo que todo su equipo disminuya la velocidad, por lo que se verá peor en un flujo de trabajo muy exigente)

Personalmente prefiero escribir código PHP de procedimiento, aunque puedo y he escrito programas completos usando OOP en algunos idiomas diferentes. Dicho esto, he visto un buen código OOP y un mal código OOP, y un buen código de procedimiento y un código de procedimiento malo para el caso ... Realmente no tiene nada que ver con la práctica, sino con los hábitos que usa e incluso entonces, muchas cosas son mis sentimientos interpretados ... eso no significa que voy a hablar mal de esos desarrolladores o decir alardear con "mi camino es el mejor" BS, es justo para mí, y la empresa para la que trabajo es bastante feliz con mi trabajo y estoy orgulloso de eso. Hay razones por las que se debe establecer un estándar, pero lo que incluya en el estándar que elija es MUY importante ... Gracias por dejarme sacar eso de mi pecho. Que tengas un gran día.


-4
  1. Las interfaces son parte del paradigma OOP. Por lo tanto, es muy útil en muchos casos cuando intenta hacer partes orientadas a objetos o su sistema.
  2. Asi que. Por qué no? ;-)

Ejemplos: necesita almacenar en caché sus datos. ¿Cómo? Hay muchos motores diferentes para el almacenamiento en caché, ¿cuál es el mejor? A quién le importa si tiene una capa abstracta que tiene una interfaz ICacheDriver con un conjunto de métodos como key, get, put, clear, etc. Simplemente implemente lo que necesita en el proyecto actual y cámbielo cuando necesite otro. O uso simple de toString. Tienes un conjunto de diferentes objetos visibles. Simplemente implementa la interfaz Stringable (que describe el método toString [en realidad no hay interfaces como esa en PHP, pero por ejemplo]) e interacciona sobre todo su objeto con (string) $ obj. Hay todo lo que necesita hacer en lugar de cambiar (verdadero) {case $ obj isntanceof A1: "do 1"; descanso; ...}

Simple. Entonces no hay duda "¿Por qué?". Hay "cómo usar eso mejor?". ;-) Buena suerte.


-5

Mi conjetura.

PHP es utilizado por muchos programadores de nivel de entrada, los programadores de nivel de entrada se les enseña Java en la universidad.

Después de su curso de Programación 101, comienzan a molestar a Zend y quieren funciones de Java porque esa es la forma en que se les ha enseñado a pensar, pensar en sus propios términos (o entender la escritura de los patos) es difícil, cuando solo tienes 20 años.

Zend es pragmático, es más fácil agregar la función que no sea fingir que están bien todo el tiempo.
Esto también compra más usuarios en lugar de obligarlos a irse, por lo que debe ser bueno.

¿Otra instancia de este proceso? Las personas recién salidas de los cursos .NET y Java también quieren Frameworks of Foundation Classes , se quejan de eso hasta que Zend brota de Zend Framework . Esto compra aún más usuarios. Y así sucesivamente...

(la única característica del lenguaje por la que se sabe que el equipo PHP ha luchado , a lo largo de los años, es goto)


En mi visión, PHP12probablemente tenga todas las características de sintaxis del mundo (espero que no obtenga un tiempo de ejecución de la capa de abstracción, difícil, ya que eso es lo que mató a Perl) con un guiño a los paradigmas funcionales y de tipo de datos, y aún no goto.
ZJR

"es difícil cuando solo tienes 20 años" ¿Cómo podría la edad tener algo que ver con la comprensión de alguno de esos conceptos?
Evicatos

@Evicatos tipo de programa para estudiantes de secundaria, pero generalmente tienen malos maestros, convenciones de nomenclatura deficientes y producen blobs insostenibles. Aprenden a programar correctamente al comenzar la universidad, les lleva un par de años ponerlo en marcha. Luego comienzan a divergir de los idiomas de tipo duro, bendecidos por la industria, aclamados por la academia, que se les han enseñado en esos primeros años, y se vuelven a los más pragmáticos, de tipo pato. Creo que este es un bushido que muchos programadores comparten. Por otra parte, esto podría no reflejar su experiencia, podría ser un sabio autodidacta. Si es así, muéstranos el camino.
ZJR
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.