Resumen: Este artículo discutirá el concepto de polimorfismo y su aplicación en el diseño orientado a objetos. También analizará cómo utilizar el polimorfismo en PHP 5 y sus ventajas y desventajas.
La compatibilidad con el enlace tardío se ha implementado en versiones recientes de PHP. Por supuesto, todavía existen muchos problemas al utilizar su función de enlace tardío. Si está utilizando una versión anterior de PHP (mi servidor ejecuta PHP 5.0.1), es posible que falte soporte para el enlace tardío. Por lo tanto, tenga en cuenta que es posible que el código de este artículo no funcione en su versión específica de PHP 5.
1. PHP 5 y polimorfismo
Este artículo quisiera discutir una de las partes más importantes de la programación orientada a objetos: el diseño del polimorfismo. Para ilustrar el problema, estoy usando PHP 5. Antes de continuar leyendo, aclare que este artículo no trata exclusivamente sobre PHP. Aunque el lenguaje ha logrado grandes avances en su rápido desarrollo en las últimas dos versiones principales, su soporte de objetos todavía tiene algo de tiempo antes de que pueda rivalizar con lenguajes más maduros como C++ o Java.
Si es un principiante en programación orientada a objetos, es posible que este artículo no sea adecuado para usted, porque esta parte del polimorfismo es especial: una vez que la comprenda, nunca la olvidará. Si desea aprender un poco sobre programación y diseño de objetos y no sabe muy bien qué significa cuando alguien dice "un objeto es polimórfico", entonces este artículo es para usted.
Al final de este artículo, sabrá qué es el polimorfismo y cómo aplicarlo al diseño orientado a objetos, y comprenderá las ventajas y desventajas de la programación de objetos en PHP 5.
2. ¿Qué es el polimorfismo?
La definición de polimorfismo de Dictionary.com es "que ocurre en diferentes formas, etapas o tipos en organizaciones independientes o en la misma organización sin diferencias fundamentales". A partir de esta definición, podemos pensar que el polimorfismo sexual es una forma de programación de describir lo mismo. objeto a través de múltiples estados o fases. De hecho, su verdadero significado es que en el desarrollo real, solo debemos centrarnos en la programación de una interfaz o clase base, y no tenemos que preocuparnos por la clase específica (clase) a la que pertenece un objeto.
Si está familiarizado con los patrones de diseño, incluso si solo tiene una comprensión preliminar, comprenderá este concepto. De hecho, el polimorfismo puede ser la mejor herramienta en la programación de diseño basada en patrones. Nos permite organizar objetos similares de forma lógica para que no tengamos que preocuparnos por el tipo específico del objeto al codificar; además, solo necesitamos programar una interfaz o clase base deseada. Cuanto más abstracta es una aplicación, más flexible se vuelve, y el polimorfismo es una de las mejores formas de abstraer el comportamiento.
Por ejemplo, consideremos una clase llamada Persona. Podemos subclasificar Persona con clases llamadas David, Charles y Alejandro. La persona tiene un método abstracto AcceptFeedback() y todas las subclases deben implementar este método. Esto significa que cualquier código que utilice una subclase de la clase Persona base puede llamar al método AcceptFeedback(). No es necesario comprobar si el objeto es un David o un Alejandro, basta con saber que es una Persona. Como resultado, su código sólo necesita centrarse en el "mínimo común denominador": la clase Persona.
La clase Persona en este ejemplo también podría crearse como una interfaz. Por supuesto, existen algunas diferencias en comparación con lo anterior, principalmente: una interfaz no proporciona ningún comportamiento, solo determina un conjunto de reglas. Una interfaz Person requiere "Debe admitir el método AddFeedback()", mientras que una clase Person puede proporcionar algún código predeterminado para el método AddFeedback(); su comprensión de esto puede ser "Si elige no admitir AddFeedback(), entonces Debe proporcionar una implementación predeterminada. "Cómo elegir una interfaz o una clase base está más allá del tema de este artículo; sin embargo, en general, debe implementar un método predeterminado a través de la clase base. También puede utilizar una interfaz si simplemente puede delinear un conjunto deseado de funcionalidades que implementa su clase.
3. Aplicar diseño polimórfico
Continuaremos usando el ejemplo de la clase base Persona y ahora analicemos una implementación no polimórfica. Los siguientes ejemplos utilizan diferentes tipos de objetos Persona, una forma de programación muy insatisfactoria. Tenga en cuenta que se omite la clase Persona real. Hasta ahora sólo nos hemos ocupado del tema de las llamadas de código.
<?php
$nombre = $_SESSION['nombre'];
$miPersona = Persona::GetPerson($nombre);
cambiar (get_class($miPersona)){
caso 'David':
$myPerson->AddFeedback('¡Excelente artículo!', 'Algún lector', fecha('Ym-d'));
romper;
caso 'Carlos':
$myPerson->feedback[] = array('Algunos lectores', '¡Excelente edición!');
romper;
caso 'Alejandro':
$miPersona->Comentarios->Append('¡Impresionante Javascript!');
romper;
por defecto :
$miPersona->AddFeedback('¡Sí!');
}
?>
Este ejemplo muestra objetos con diferentes comportamientos y se utiliza una declaración de cambio para distinguir diferentes objetos de clase Persona para realizar sus respectivas operaciones correctas. Tenga en cuenta que los comentarios aquí son diferentes para diferentes condiciones. Puede que este no sea el caso en el desarrollo de aplicaciones reales; simplemente ilustro las diferencias que existen en las implementaciones de clases.
Un ejemplo a continuación utiliza polimorfismo.
<?php
$nombre = $_SESSION['nombre'];
$miPersona = Persona::GetPerson($nombre);
$myPerson->AddFeedback('¡Excelente artículo!', 'SomeReader', date('Ym-d'));
?>
Tenga en cuenta que aquí no hay una declaración de cambio y, lo más importante, falta información sobre qué tipo de objeto devolverá Person::GetPerson(). Y el otro Person::AddFeedback() es un método polimórfico. El comportamiento está completamente encapsulado por clases concretas. Recuerde, ya sea que estemos usando David, Charles o Alejandro aquí, el código de llamada nunca tiene que saber qué hace la clase concreta, solo la clase base.
Aunque mi ejemplo no es perfecto, demuestra el uso básico del polimorfismo desde la perspectiva del código de llamada. Ahora necesitamos analizar la implementación interna de estas clases. Una de las ventajas de derivar de una clase base es que la clase derivada puede acceder al comportamiento de la clase principal. Esta suele ser la implementación predeterminada, pero también puede ocurrir en cadenas de herencia de clases para crear un comportamiento más complejo. A continuación se muestra una demostración sencilla de esta situación.
<?php
persona de clase {
función AddFeedback($comentario, $remitente, $fecha){
//Agregar comentarios a la base de datos}
}
clase David extiende Persona{
función AddFeedback($comentario, $remitente){
padre::AddFeedback($comentario, $remitente,
fecha('Ym-d'));
}
}
?>
Aquí, el método Person::AddFeedback se llama por primera vez en la implementación del método AddFeedback en la clase David. Puede notar que imita la sobrecarga de métodos en C++, Java o C#. Tenga en cuenta que este es sólo un ejemplo simplificado y que el código real que escriba depende completamente de su proyecto real.
4. Enlace tardío en PHP 5
En mi opinión, el enlace tardío es una razón importante por la que Java y C# son tan atractivos. Permiten que los métodos de la clase base llamen a métodos usando "this" o $this (incluso si no existen en la clase base o la llamada a un método en la clase base puede ser reemplazada por otra versión en la clase heredada). Puede considerar que se permiten las siguientes implementaciones en PHP:
<?php
persona de clase {
función Agregar comentarios($messageArray) {
$this->ParseFeedback($messageArray);
//Escribir en la base de datos}
}
clase David extiende Persona{
función ParseFeedback($messageArray){
//Hacer un análisis}
}
?>
Recuerde, no hay ParseFeedback en la clase Persona. Ahora, asumiendo que tienes esta parte del código de implementación (para este ejemplo), esto hará que $myPerson sea un objeto David:
<?php
$miPersona = Persona::GetPerson($nombre);
$miPersona->AddFeedback($messageArray);
?> ¡
Ocurrió un error de análisis! El mensaje de error general es que el método ParseFeedback no existe o alguna información similar. ¡Hablemos del enlace tardío en PHP 5! A continuación, resumamos el concepto de vinculación tardía.
La vinculación tardía significa que la llamada al método no está vinculada al objeto de destino hasta el último momento. Esto significa que cuando se llama al método en tiempo de ejecución, esos objetos ya tienen un tipo concreto. En nuestro ejemplo anterior, llamaste a David::AddFeedback(), y dado que $this en David::AddFeedback() se refiere a un objeto David, puedes asumir lógicamente que el método ParseFeedback() existe, pero en realidad no es así. existe porque AddFeedback() está definido en Person y ParseFeedback() se llama desde la clase Person.
Desafortunadamente, no existe una manera fácil de eliminar este comportamiento en PHP 5. Esto significa que puede que te sientas un poco impotente cuando quieras crear una jerarquía de clases polimórfica flexible.
Debo señalar que elegí PHP 5 como lenguaje de expresión para este artículo simplemente porque: ¡este lenguaje no realiza la abstracción perfecta del concepto de objeto! Esto es comprensible ya que PHP 5 aún se encuentra en su versión beta. Además, ahora que se agregan clases e interfaces abstractas al lenguaje, también se debe implementar el enlace tardío.
5. Resumen
En este punto, debes tener una comprensión básica de qué es el polimorfismo y por qué PHP 5 no es perfecto para lograr el polimorfismo. En general, debes saber cómo utilizar un modelo de objetos polimórficos para encapsular el comportamiento condicional. Por supuesto, esto aumenta la flexibilidad de sus objetos y significa menos código para implementar. Además, aumenta la claridad de su código encapsulando comportamientos que satisfacen ciertas condiciones (dependiendo del estado del objeto).