2010-08-01 14 views
7

Uno de los principales principios de diseño es el programa para una interfaz, no una implementación. ¿Es esto posible en php o en cualquier otro lenguaje débilmente tipado?Programa para una interfaz no una implementación en php

EDIT:

que tal vez aún no ha escribir la pregunta tan claramente como debería haberlo hecho. No quiero decir que php no puede usar interfaces, obviamente puede hacerlo. Me refiero a que el principio de diseño "programa a una interfaz y no a una implementación" se vuelve redundante en los lenguajes débilmente tipados.

+0

Ver mi publicación editada. No puedo ver por qué sería "redundante" – NullUserException

Respuesta

4

Sí. Definir la interfaz:

interface iTemplate 
{ 
    public function setVariable($name, $var); 
    public function getHtml($template); 
} 

Y ponerlo en práctica:

// Implement the interface 
class Template implements iTemplate 
{ 
    private $vars = array(); 

    public function setVariable($name, $var) 
    { 
     $this->vars[$name] = $var; 
    } 

    public function getHtml($template) 
    { 
     foreach($this->vars as $name => $value) { 
      $template = str_replace('{' . $name . '}', $value, $template); 
     } 

     return $template; 
    } 
} 

manual de PHP en interfaces: http://php.net/manual/en/language.oop5.interfaces.php

No sé por qué no sería posible tener interfaces sólo porque el el lenguaje está débilmente tipado.


EDIT: El punto (más o menos) de tener una interfaz es para que pueda volver a utilizar su código, independientemente de la clase que realmente implementa dicha interfaz.

Supongamos que su programa utiliza una interfaz Set, que tiene los métodos addItem(), removeItem() y . Con las interfaces, usted sabe que podrá llamar a cualquiera de estos 3 métodos independientemente de la implementación subyacente de Set, ya sea HashSet, TreeSet o lo que sea.

Esto no cambia si está utilizando un lenguaje débilmente tipado; aún puede codificar como si estuviera usando un lenguaje fuertemente tipado. Sé que no dije esta explicación muy bien, pero espero que entiendas la idea.

0

php tiene interfaces y usted puede programarlos. ¿Por qué no puedes hacer eso?

La programación en una interfaz significa que solo utiliza la funcionalidad que ofrece la interfaz y no confía en los detalles de implementación ni utiliza otras funcionalidades que ofrece la implementación y simplemente sabe de ella, porque la implementación podría cambiar (la interfaz no debería).

+0

Bueno, el objetivo principal del principio parece no tener sentido cuando no estás usando tipos. Claro que puedes usar interfaces en php, obviamente no estoy disputando eso, estoy diciendo que el principio no es efectivo cuando no puedes usar el tipo de objeto. Por ejemplo, en un lenguaje de tipo fuerte, debería usar: Escriba t = new ConcreteType - en php simplemente dice $ t = new ConcreteType. Sure ConcreteType implementará la interfaz pero el código de instanciación no sabe nada sobre esto. Tal vez estoy malinterpretando el principio. – David

+0

@David Seguramente pierden algunas de sus ventajas en un lenguaje débilmente tipado, pero siguen siendo útiles si se usan correctamente. – NullUserException

+0

Pero el principio está destinado a que "una vez que dependas solo de las interfaces, estés desacoplado de la implementación" E Gama, pero en un lenguaje débilmente tipeado estás simplemente usando la clase concreta al crear instancias. Simplemente no puedo ver cómo se aplica el principio aquí. Probablemente estoy siendo estúpido, pero por alguna razón se me viene encima. – David

0

Depende de lo que quiere decir con "interfaz" e "implementación". Estos son términos sueltos cuyos significados pueden cambiar dependiendo del contexto.

PHP5 contiene construcciones OOP similares a Java y C#, tales como Objetos como referencias, Clases, Clases abstractas e Interfaces. También contiene sugerencias de tipo para los parámetros del método. Estas herramientas podrían ser, y han sido, utilizadas para construir "una interfaz" para algo.

0

El objetivo final es tener una interfaz en la que cada componente esté de acuerdo.

Entonces, si, por ejemplo, estaba construyendo un sitio de JavaScript que se hacía -en su totalidad- en una implementación MVC (non-Rails/PHP) de la vieja escuela, y completamente en AJAX, me aseguraría de que cada uno los componentes implementaron la misma interfaz para la observación.

En cada modelo/vista/controlador, podría nombrar mi método de "suscripción" algo completamente diferente. O bien, podría implementar una interfaz estándar para cada uno.

De modo que puedo tener un método público ".Register (event_type, subscribing_class)" implementado en TODOS los componentes únicos de los que podría esperarse llamar.

Del mismo modo, puedo tener un método público ".Update (event_type, data)" implementado en CADA componente que podría esperarse que se llame.

The .Register y .Update son la interfaz para mi comunicación Observer. Dentro de mis clases, cada una puede tener un método ".Subscribe (publisher, event_type, self_reference)". Ese método podría ser:

Class.Subscribe = function (publisher, event_type) { 
    var self_reference = this; 
    publisher.Register(event_type, self_reference); 
}; 

Cada podrían tener un método .Notify interna:

Class.Notify = function (type, data) { 
    var subscribers = this.subscribers[type], 
     i = 0, l = subscribers.length; 

    for (; i < l; i++) { subscribers[i].Update(type, data); } 
}; 

Debido he acordado que todos los de mi interfaz de comunicación va a comportarse de esta manera, no importa cómo se vean mis internos.

Mi modelo puede seguir sin tener en cuenta mi Vista, y mi vista puede seguir siendo ajena a mi controlador.

El .Notify y .Subscribe no necesitan ser implementados de esa manera, no son parte de la interfaz de acceso público. Podrían ser lo que yo quiera.

. Suscribir podría tomar un ARRAY de editores y presionarlo a través de un bucle for, suscribirse a múltiples puntos de datos. O tome una matriz de {"pub": x, "escriba": y} literales de objeto, y llame al método .Register de cada uno, de modo que pueda obtener TODA la inicialización de esa Clase con una llamada a una función.

Lo mismo ocurre con la creación de una aplicación de reproductor de audio. No me importa qué propiedades públicas comparta MusicPlayer. Sé que usa .Play(), .Pause(), .Stop(), .Load (track).

Si me aseguro de que SÓLO uso los métodos de interfaz públicos acordados, el programa funcionará. ¿Por qué?

Porque el chico que trabaja en MusicPlayer podría cambiar las partes internas de MusicPlayer. Podría reescribirlos completamente. Tal vez haya un ._ método precacheSong (seguimiento). Pero, ¿qué pasa si se reemplaza con. _cueTrack (pista) por el camino?

Usted solo está usando el widget de algún amigo, y un día su widget se cuelga, porque lo estaba extendiendo o implementándolo en base a métodos que no son de interfaz o datos que no son de interfaz, que cambió a partir de v1.2.1

Por lo tanto, incluso en Loose Languages, la interfaz es importante. Le dan un mapa de cómo puede esperar llamar a CUALQUIER componente que se espera que tenga esa funcionalidad, e independientemente de cómo funcionan las funciones internas de ese componente, las entradas y salidas serán exactamente las mismas (aunque más tipo/error) es necesario verificar las entradas).

Le permiten "Tipo de pato" realmente fácil (tome una lista de diferentes instancias de Clase - active la misma llamada de función en cada una, esperando que cada una tenga el mismo método y tome el mismo formato de datos).

Incluso mejor con JavaScript:

Mi código .Subscribe incluso podría escribir solamente una vez, y luego ligado a todo lo que yo quiero "heredar" la misma.

Interface.Subscribe = function (publisher, evt_type) { 
    var self_ref = this; 
    publisher.Register(evt_type, self_ref); 
}; 

Class_1.Subscribe = Interface.Subscribe.bind(Class_1); 
Class_2.Subscribe = Interface.Subscribe.bind(Class_2); 
Class_3.Subscribe = Some_Other_Interface.Subscribe.bind(Class_3); 

Y yo puedo hacer eso libremente, porque sé que todo lo que quiero para suscribirse a va a tener la misma interfaz pública.

Cuestiones relacionadas