En la programación orientada a objetos, el polimorfismo es una herramienta poderosa y fundamental. Puede usarse para crear un flujo más orgánico en su aplicación. Este tutorial describirá el concepto general de polimorfismo y cómo se puede implementar fácilmente en PHP.
Polimorfismo es una palabra larga para un concepto muy simple..
El polimorfismo describe un patrón en la programación orientada a objetos en el que las clases tienen una funcionalidad diferente al compartir una interfaz común.
La belleza del polimorfismo es que el código que trabaja con las diferentes clases no necesita saber qué clase está usando, ya que todas se usan de la misma manera..
Una analogía del mundo real para el polimorfismo es un botón. Todo el mundo sabe cómo usar un botón: simplemente le presionas. Sin embargo, lo que hace un botón "depende" de a qué está conectado y del contexto en el que se usa, pero el resultado no afecta la forma en que se usa. Si su jefe le dice que presione un botón, ya tiene toda la información necesaria para realizar la tarea..
En el mundo de la programación, el polimorfismo se utiliza para hacer que las aplicaciones sean más modulares y extensibles. En lugar de desordenadas declaraciones condicionales que describen diferentes cursos de acción, crea objetos intercambiables que selecciona según sus necesidades. Ese es el objetivo básico del polimorfismo..
Una parte integral del polimorfismo es la interfaz común. Hay dos formas de definir una interfaz en PHP: interfaces y clases abstractas. Ambos tienen sus usos, y puedes mezclarlos y combinarlos como mejor te parezca en tu jerarquía de clases.
Una interfaz es similar a una clase, excepto que no puede contener código. Una interfaz puede definir nombres y argumentos de métodos, pero no el contenido de los métodos. Cualquier clase implementando una interfaz. debe Implementar todos los métodos definidos por la interfaz. Una clase puede implementar múltiples interfaces..
Se declara una interfaz usando el 'interfaz
'palabra clave:
interfaz MyInterface // métodos
y se adjunta a una clase utilizando el 'implementos
'palabra clave (se pueden implementar múltiples interfaces al enumerarlas separadas por comas):
La clase MyClass implementa MyInterface // métodos
Los métodos se pueden definir en la interfaz al igual que en una clase, excepto sin el cuerpo (la parte entre las llaves):
interfaz MyInterface public function doThis (); función pública doThat (); función pública setName ($ nombre);
Todos los métodos definidos aquí deberán incluirse en cualquier clase de implementación exactamente como se describe. (lea los comentarios del código a continuación)
// La clase VALID MyClass implementa MyInterface nombre protegido de $; función pública doThis () // código que hace esta función pública doThat () // código que hace esa función pública setName ($ nombre) $ this-> name = $ nombre; // clase INVALIDA MyClass implementa MyInterface // falta doThis ()! función privada doThat () // ¡esto debería ser público! función pública setName () // falta el argumento del nombre!
Una clase abstracta es una mezcla entre una interfaz y una clase. Puede definir la funcionalidad y la interfaz (en forma de métodos abstractos). Clases que amplían una clase abstracta. debe Implementar todos los métodos abstractos definidos en la clase abstracta..
Una clase abstracta se declara de la misma manera que las clases con la adición de 'resumen
'palabra clave:
clase abstracta MyAbstract // métodos
y se adjunta a una clase utilizando el 'se extiende
'palabra clave:
clase MyClass extiende MyAbstract // métodos de clase
Los métodos regulares se pueden definir en una clase abstracta al igual que en una clase regular, así como cualquier método abstracto (usando la 'resumen
'palabra clave). Los métodos abstractos se comportan como los métodos definidos en una interfaz, y deben implementarse exactamente como se define al extender las clases.
clase abstracta MyAbstract nombre público $; función pública doThis () // hacer esto función pública abstracta doThat (); Resumen función pública setName ($ nombre);
Imaginemos que tienes un Artículo
Clase que se encarga de gestionar los artículos en su sitio web. Contiene información sobre un artículo, incluido el título, el autor, la fecha y la categoría. Esto es lo que parece:
class poly_base_Article public $ title; autor público $ fecha $ pública categoría $ pública; función pública __construct ($ title, $ author, $ date, $ category = 0) $ this-> title = $ title; $ this-> author = $ author; $ this-> date = $ date; $ this-> category = $ category;
Nota: Las clases de ejemplo en este tutorial utilizan la convención de nomenclatura de "package_component_Class". Esta es una forma común de separar las clases en espacios de nombres virtuales para evitar colisiones de nombres.
Ahora desea agregar un método para generar la información en diferentes formatos, como XML y JSON. Podrías estar tentado a hacer algo como esto:
clase poly_base_Article //… escritura de función pública ($ tipo) $ ret = "; switch ($ tipo) caso 'XML': $ ret = ''; $ ret. = ' '; descanso; caso 'JSON': $ array = array ('article' => $ obj); $ ret = json_encode ($ array); descanso; devuelve $ ret;'. $ obj-> título. ' '; $ ret. = ''. $ obj-> autor. ' '; $ ret. = ''. $ obj-> fecha. ' '; $ ret. = ''. $ obj-> categoría. ' '; $ ret. = '
Esta es una especie de solución fea, pero funciona, por ahora. Sin embargo, pregúntese qué sucede en el futuro, cuando queremos agregar más formatos. Puedes seguir editando la clase, agregando más y más casos, pero ahora solo estás diluyendo tu clase.
Un principio importante de la POO es que una clase debe hacer una cosa y debe hacerlo bien.
Teniendo esto en cuenta, las declaraciones condicionales deben ser una bandera roja que indica que su clase está tratando de hacer demasiadas cosas diferentes. Aquí es donde entra el polimorfismo.
En nuestro ejemplo, está claro que se presentan dos tareas: administrar artículos y dar formato a sus datos. En este tutorial, refactorizaremos nuestro código de formato en un nuevo conjunto de clases y descubriremos lo fácil que es usar polimorfismo.
Lo primero que debemos hacer es definir la interfaz. Es importante pensar detenidamente acerca de su interfaz, ya que cualquier cambio en ella puede requerir cambios en el código de llamada. En nuestro ejemplo, usaremos una interfaz simple para definir nuestro único método:
interface poly_writer_Writer public function write (poly_base_Article $ obj);
Es así de simple; hemos definido un público escribir()
Método que acepta un objeto artículo como argumento. Cualquier clase que implemente la interfaz de Writer tendrá este método..
Propina: Si desea restringir el tipo de argumentos que se pueden pasar a sus funciones y métodos, puede utilizar sugerencias de tipo, como hemos hecho en el escribir()
método; solo acepta objetos de tipo poly_base_Article
. Desafortunadamente, las sugerencias de tipo de retorno no son compatibles con las versiones actuales de PHP, por lo que depende de usted cuidar los valores de retorno..
Con su interfaz definida, es hora de crear las clases que realmente hacen cosas. En nuestro ejemplo, tenemos dos formatos que queremos generar. Por lo tanto, tenemos dos clases de escritor: XMLWriter y JSONWriter. Depende de estos extraer los datos del objeto Artículo pasado y formatear la información.
Así es como se ve XMLWriter:
La clase poly_writer_XMLWriter implementa poly_writer_Writer public function write (poly_base_Article $ obj) $ ret = ''; $ ret. = ' '; devuelve $ ret;'. $ obj-> título. ' '; $ ret. = ''. $ obj-> autor. ' '; $ ret. = ''. $ obj-> fecha. ' '; $ ret. = ''. $ obj-> categoría. ' '; $ ret. = '
Como se puede ver en la declaración de clase, usamos el implementos
Palabra clave para implementar nuestra interfaz. los escribir()
método contiene funcionalidad específica para formatear XML.
Ahora aquí está nuestra clase JSONWriter:
la clase poly_writer_JSONWriter implementa poly_writer_Writer public function write (poly_base_Article $ obj) $ array = array ('article' => $ obj); devolver json_encode ($ array);
Todo nuestro código específico para cada formato ahora está contenido dentro de clases individuales. Cada una de estas clases tiene la responsabilidad exclusiva de manejar un formato específico, y nada más. Ninguna otra parte de su aplicación debe preocuparse por cómo funcionan estas para usarla, gracias a nuestra interfaz.
Con nuestras nuevas clases definidas, es hora de revisar nuestra clase de artículo. Todo el código que vivió en el original. escribir()
método ha sido factorizado en nuestro nuevo conjunto de clases. Todo lo que nuestro método tiene que hacer ahora es usar las nuevas clases, como esto:
clase poly_base_Article // ... public function write (poly_writer_Writer $ writer) return $ writer-> write ($ this);
Todo lo que este método hace ahora es aceptar un objeto de la clase Writer (es decir, cualquier clase que implemente la interfaz de Writer), llamar a su escribir()
método, pasando a sí mismo ($ esto
) como argumento, luego reenvíe su valor de retorno directamente al código del cliente. Ya no tiene que preocuparse por los detalles del formato de los datos, y puede centrarse en su tarea principal.
Puede que se esté preguntando dónde puede obtener un objeto Writer, ya que necesita pasar uno a este método. Eso depende de usted, y hay muchas estrategias. Por ejemplo, puede usar una clase de fábrica para capturar datos de solicitud y crear un objeto:
class poly_base_Factory función estática pública getWriter () // agarrar variable de solicitud $ formato = $ _REQUEST ['formato']; // construye nuestro nombre de clase y verifica su existencia $ class = 'poly_writer_'. $ formato. 'Escritor'; if (class_exists ($ class)) // devolver un nuevo objeto Writer devolver new $ class (); // de lo contrario, fallaremos lanzar una nueva excepción ('Formato no compatible');
Como dije, hay muchas otras estrategias para usar dependiendo de sus requisitos. En este ejemplo, una variable de solicitud elige qué formato usar. Construye un nombre de clase a partir de la variable de solicitud, verifica si existe y luego devuelve un nuevo objeto Writer. Si no existe ninguno con ese nombre, se lanza una excepción para permitir que el código del cliente determine qué hacer.
Con todo en su lugar, aquí está cómo nuestro código de cliente lo pondría todo junto:
$ article = new poly_base_Article ('Polymorphism', 'Steve', time (), 0); intente $ writer = poly_base_Factory :: getWriter (); catch (Exception $ e) $ writer = new poly_writer_XMLWriter (); echo $ articulo-> escribir ($ escritor);
Primero creamos un objeto de artículo de ejemplo para trabajar. Luego tratamos de obtener un objeto Writer de la fábrica, volviendo a un valor predeterminado (XMLWriter) si se produce una excepción. Finalmente, pasamos el objeto Escritor a nuestros artículos. escribir()
Método, imprimiendo el resultado..
En este tutorial, te proporcioné una introducción al polimorfismo y una explicación de las interfaces en PHP. Espero que te des cuenta de que solo te he mostrado un posible caso de uso para el polimorfismo. Hay muchas, muchas más aplicaciones. El polimorfismo es una forma elegante de escapar de las declaraciones condicionales feas en su código OOP. Sigue el principio de mantener sus componentes separados y es una parte integral de muchos patrones de diseño. Si tienes alguna duda, no dudes en preguntar en los comentarios.!