Programación Orientada a Objetos en PHP

10
1 Programación Orientada a Objetos en PHP Publicado en http://www.zonaphp.com/ por Webstudio el February 24th, 2003 Este artículo escrito originalmente por Luis Argerich nos introducirá a la Programación Orientada a Objetos (POO o su versión inglesa: OOP) en PHP. En él veremos la forma de programar menos y mejor usando conceptos de POO junto con algunos trucos de PHP. Programación Orientada a Objetos en PHP Algunos "puristas" afirmarán que PHP no es un verdadero lenguaje orienteado a objetos, lo que es cierto. PHP es un lenguaje híbrido dónde se pueden utilizar POO y programación estructurada tradicional. Pero para ciertos proyectos grandes, quizas deseemos/necesitemos(?) usar POO "pura" en PHP, declarando Clases y solo utilizando Objetos y Clases para el proyecto. Mientras emergen dia a dia proyectos más y más grandes, el uso de POO puede ayudar, el código POO es fácil de mantener, facíl de comprender y fácil de reusar. Y estos son los principios de la Ingeniería de Software. Aplicar estos conceptos en proyectos basados en la web, es la clave para el éxito de futurios sitios web. Este artículo es una introducción a la Programación Orientada a Objetos en PHP. Intentaremos mostrarles como se puede programar menos y mejor utilizando algunos conceptos de POO y trucos de PHP. Buena Suerte ! Conceptos de programación orientada a objetos: aunque existen diferencias entre distintos autores, puedo decirles que un lenguaje de POO debe poseer: Tipos Abstractos de Datos y ocultamiento de la Información Herencia Polimorfismo El encapsulamiento en PHP se logra utilizando clases: PHP: 1. <?php 2. class Algo 3. { 4. // En PHP, las clases usualmente se nombran con la primera letra en mayúscula. 5. var $x; 6. 7. function setX($v) 8. { 9. // Los Métodos comienzan en minúscula y luego se usan mayúsculas para 10. // separar palabras en el nombre del método. 11. // Ejemplo : obtenerRaizCuadrada(); 12. $this->x = $v; 13. }

description

Programación Orientada a Objetos en PHP

Transcript of Programación Orientada a Objetos en PHP

Page 1: Programación Orientada a Objetos en PHP

1

Programación Orientada a Objetos en PHPPublicado en http://www.zonaphp.com/ por Webstudio el February 24th, 2003

Este artículo escrito originalmente por Luis Argerich nos introducirá a la ProgramaciónOrientada a Objetos (POO o su versión inglesa: OOP) en PHP. En él veremos la forma deprogramar menos y mejor usando conceptos de POO junto con algunos trucos de PHP.

Programación Orientada a Objetos en PHP

Algunos "puristas" afirmarán que PHP no es un verdadero lenguaje orienteado a objetos, loque es cierto. PHP es un lenguaje híbrido dónde se pueden utilizar POO y programaciónestructurada tradicional. Pero para ciertos proyectos grandes, quizasdeseemos/necesitemos(?) usar POO "pura" en PHP, declarando Clases y solo utilizandoObjetos y Clases para el proyecto. Mientras emergen dia a dia proyectos más y más grandes,el uso de POO puede ayudar, el código POO es fácil de mantener, facíl de comprender yfácil de reusar. Y estos son los principios de la Ingeniería de Software. Aplicar estosconceptos en proyectos basados en la web, es la clave para el éxito de futurios sitios web.

Este artículo es una introducción a la Programación Orientada a Objetos en PHP.Intentaremos mostrarles como se puede programar menos y mejor utilizando algunosconceptos de POO y trucos de PHP. Buena Suerte !

Conceptos de programación orientada a objetos: aunque existen diferencias entre distintosautores, puedo decirles que un lenguaje de POO debe poseer:

Tipos Abstractos de Datos y ocultamiento de la Información Herencia Polimorfismo

El encapsulamiento en PHP se logra utilizando clases:

PHP:

1. <?php2. class Algo3. {4. // En PHP, las clases usualmente se nombran con la primera letra

en mayúscula.5. var $x;6.7. function setX($v)8. {9. // Los Métodos comienzan en minúscula y luego se usan

mayúsculas para10. // separar palabras en el nombre del método.11. // Ejemplo : obtenerRaizCuadrada();12. $this->x = $v;13. }

Page 2: Programación Orientada a Objetos en PHP

2

14.15. function getX()16. {17. return $this->x;18. }19.}20. ?>

Los atributos de los objetos se definen en PHP utilizando la declaración "var" dentro de laclase, estos atributos no tienen tipo hasta que se les asigna un valor. Un atributo puee ser unentero, un arreglo, un arreglo asociativo o incluso otro objeto. Los métodos se definencomo funciones dentro de la clase, para acceder a los atributos dentro de los métodos sedebe utilizar $this->nombre, de otra manera, se utilizaria una variable local al método.

Para crear (instanciar) un nuevo objeto se utiliza el operador new:

$obj = new Algo;

Luego, se pueden acceder a sus métodos asi:

PHP:

1. $obj->setX(5);2. $valor=$obj->getX();

El método setx le asigna el valor 5 al atributo x en el objeto obj (no a la clase), entoncesgetx devuelve ese valor: 5 en este caso.

En realidad también se puede acceder a los atributos del objeto de esta manera: $obj->x = 6;sin embargo esta no es una buena práctica de POO. Yo recomiendo acceder a los atributosdefiniendo métodos para asignarlos y devolverlos. Serás un buen programador orientado aobjetos si considerás los atributos como innacesibles y solo utilizando métodos paraacceder a ellos. Lamentablemente, PHP aún no ofrece una manera de definir un atributocomo privado asi que una mala programación es posible.

La Herencia es sencilla de utilizar en PHP con la palabra reservada extend.

PHP:

1. <?php2. class Otra extends Algo3. {4. var $y;5. function setY($v)6. {7. $this->y = $v;8. }9.10. function getY()11. {

Page 3: Programación Orientada a Objetos en PHP

3

12. return $this->y;13. }14.}15. ?>

Objetos de la clase "Otra" ahora poseen todos los atributos y métodos de la clase padre(Algo) más sus propios métodos y atributos. Se puede hacer:

PHP:

1. $obj2=new Otra;2. $obj2->setX(6);3. $obj2->setY(7);

La Herencia múltiple no está soportada por PHP así que no se puede hacer que una claseextienda dos o más clases diferentes.

Se puede sobreescribir un método en la clase derivada tan solo redefiniéndolo, siredefiniéramos getx en "Otra" ya no podríamos acceder al metodo getx en "Algo". Si sedeclara un atributo en una clase derivada con el mismo nombre de un atributo de la clasebase, el atributo derivado "esconde" al atributo de la clase base cuando se intenta acceder almismo.

Se puedden definir Constructores en las clases. Los Constructores son métodos con elmismo nombre de la clase y que son llamados en el momento en que se instancia un objeto,por ejemplo:

PHP:

1. <?php2. class Algo3. {4. var $x;5.6. function Algo($y)7. {8. $this->x=$y;9. }10.11. function setX($v)12. {13. $this->x=$v;14. }15.16. function getX()17. {18. return $this->x;19. }20.}21. ?>

Page 4: Programación Orientada a Objetos en PHP

4

Asi que ahora se puede crear al objeto asi :

$obj=new Algo(6);

Y el Constructor automáticamente asigna 6 al atributo x. Los Constructores y los métodosson funciones normales de PHP, por lo que se pueden usar argumentos por defecto.

function Algo($x="3",$y="5")

Entonces:

PHP:

1. <?php2. $obj=new Algo(); // x=3 e y=53. $obj=new Algo(8); // x=8 e y=54. $obj=new Algo(8,9); // x=8 e y=95. ?>

Los argumentos por defecto son utilizandos de la misma manera que en C++, asi que no esposible pasarle un valor a Y dejando que X tome el valor por defecto, los argumentos sonasignados de izquierda a derecha y cuando no se encuentran más argumentos, y si lafunción esperaba más de los que se enviaron, entonces los restantes toman sus valores pordefecto.

Cuando un objeto de una clase derivada es instanciado, solo su Constructor es llamado,pero no el de la clase Padre, esto es una lástima porque el encadenamiento de constructoreses una característica clásica de la POO. Si quieres llamar al constructor de la clase base, setiene que hacer explicitamente en el constructor de la clase derivada. Esto funciona porquetodos los metodos de la clase padre están disponibles en la clase derivada debido a laHerencia.

PHP:

1. <?php2. function Otra()3. {4. $this->y=5;5. $this->Algo(); //llamada explicita al contructor de la

clase padre.6. }7. ?>

Un mecanismo interesante en la POO es la utilización de Clases Abstractas, estas clases noson instanciables y su único propósito es el de definir una interfase para sus clasesderivadas. Los diseñadores y analistas generalmente utilizan Clases Abstractas para forzar alos programadores a derivar clases de ciertas clases base, y de esa manera asegurarse que

Page 5: Programación Orientada a Objetos en PHP

5

las nuevas clases tendrán ciertas funcionalidades deseadas. No existe una manera estandarde hacer esto en PHP, pero:

Si necesitas esta funcionaliad, define la clase base y coloca un "die();" en su constructor, deesta manera nos aseguramos que la clase no es instanciable, luego define sus métodos(interfase) colocando "die()" al final de cada uno, de esa manera, si un programador nosobreescribe el método entonces ocurre un error. Incluso puede ser necesario estar seguroque una clase es derivada de una clase base en particular, entonces es recomendable agregarun método en la clase base que la identifique (que retorne algun "identificador") y verificaresto cada vez que se recibe un objeto como argumento. Por supuesto esto no funciona si eldiabólico programador sobreescribe el método en la clase derivada, pero generalmente elproblema es tratar con programadores holgazanes, no con programadores diabólicos! Porsupuesto, es mejor mantener la clase base fuera del alcance de los programadores, tan solopresentarles la interfase y hacerlos trabajar.

No hay destructores en PHP.

La "Sobrecarga" ( que es diferente a la "Sobreescritura" ) no es soportada por PHP. EnPOO uno "sobrecarga" un método cuando se definen dos o tres métodos con el mismonombre, pero con diferentes números o tipos de parámetros (dependiendo del lenguaje). Noexisten tipos de datos en PHP, así que sobrecargar por tipos de datos no funciona, sinembargo, sobrecargar por cantidad de parámetros tampoco existe.

Es muy útil a veces en POO sobrecargar los Constructores para poder instanciar el objetode diferentes maneras (pasándole diferentes números de parámetros). Un truco para haceresto en PHP es:

PHP:

1. <?php2. class MiClase3. {4. function MiClase()5. {6. $nombre="MiClase".func_num_args();7. $this->$nombre();8. // Notar que $this->nombre(); generalmente estaría

mal9. // pero aqui $nombre es un string con el nombre del10. // método que se va a llamar11. }12.13. function MiClase1($x)14. {15. //código;16. }17. function MiClase2($x,$y)18. {19. //código;20. }

Page 6: Programación Orientada a Objetos en PHP

6

21.}22. ?>

Con este "trabajo extra" en la clase, el uso de la misma se vuelve transparente al usuario( de la clase, no del sitio ) :

PHP:

1. <?php2. $obj1=new MiClase('1'); // llamará a MiClase13. $obj2=new MiClase('1','2'); // llamará a MiClase24. ?>

Muchas veces esto es muy útil.

Polimorfismo

Polimorfismo se define a la habilidad de un objeto de determinar que método invocar paraun objeto pasado como argumento en tiempo de ejecución. Por ejemplo, si tenemos unaclase "Figura" que define un método para dibujar y dos clases derivadas Círculo yRectángulo dónde se sobreescriben ese método, se puede tener un método que espere unargumento "x" y luego hacer $x->dibujar(). Si tuvieramos polimorfismo, el método"dibujar" llamado dependería del tipo de objeto que se le pasa a la función. ElPolimorfismo es muy sencillo y hasta natural en lenguajes interpretados como PHP. Asique afortunadamente PHP soporta Polimorfismo.

PHP:

1. <?php2. function dibujar($x)3. {4. // Supongamos que este es un método de una clase "Pizarra"5. $x->dibujar();6. }7.8. $obj=new Círculo(3,187);9. $obj2=new Rectángulo(4,5);10.11.$pizarra->dibujar($obj); // llamará al método dibujar de Círculo.12.$pizarra->dibujar($obj2); // llamará al método dibujar de

Rectángulo.13. ?>

Técnicas avanzadas de POO en PHP

Luego de aprender los conceptos básicos de la POO, les puedo mostrar algunas técnicasmás avanzadas:

Page 7: Programación Orientada a Objetos en PHP

7

Serialización

PHP no soporta Objetos Persistentes. En POO los Objetos Persistentes son aquellos quemantienen su estado y funcionalidad a través de múltiples invocaciones de la aplicación,esto es, la habilidad de "grabar" el objeto a un archivo o base de datos y luego "cargarlo"nuevamente. Este mecanismo es conocido como Serialización. PHP tiene una función deserialización que puede ser utilizada con objetos, y devuelve una cadena que representa aese objeto. Sin embargo la serialización guarda los atributos pero no los métodos.

En PHP4, si uno serializa un objeto hacia una cadena $s, luego se destruye el objeto y luegose vuelve a des-serializar el objeto hacia $obj, aún se puede tener acceso a los métodos! Yoen realidad no recomiendo esto porque (a) La documentación no garantiza estefuncionamiento y en futuras versiones de PHP puede dejar de existir. (b) Esto puede llevara crear "ilusiones" de grabar el objeto serializado en una cadena y salir del script. En futurasejecuciones del script, no podrás des-serializar la cadena hacia un objeto y esperar que losmétodos estén alli, porque la cadena que representa al objeto no guarda los métodos delmismo. Resumiendo, la serialización en PHP es MUY útil para guardar los atributos de unobjeto, pero solo eso. (También se pueden serializar arreglos simples y asociativos paraguardarlos en disco).

Ejemplo

PHP:

1. <?php2. $obj=new ClaseFoo();3. $cadena=serialize($obj);4. // Grabamos $cadena a disco5.6. //...algunas miles de instrucciones después....7.8. //Cargamos $cadena del disco9. $obj2 = unserialize($cadena);10. ?>

Obtendremos los atributos pero no los métodos (de acuerdo a la documentación). Esto noslleva a que sea $obj2->x la única manera de acceder a los atributos (ya que no tenemosmétodos para hacerlo!) así que no intenten hacer esto en sus casas.

Hay algunas maneras de solucionar este problema, pero se las dejo para que las invetiguen,ya que son muy "chanchas" para este lindo artículo.

Serialización Completa es una característica que apreciaría mucho en futuras versiones dePHP.

Page 8: Programación Orientada a Objetos en PHP

8

Utilizando Clases para trabajar con datos almacenados

Una de las mejores cosas de la POO y PHP es que se pueden definir sencillamente clasespara manipular ciertas cosas y luego llamar a las clases apropiadas cuando sea necesiario.Supongamos que tenemos un formulario HTML dónde el usuario elige un producto,enviando su ID de producto, nosotros tenemos esa información en una base de datos yqueremos mostrar por pantalla su precio, etc, etc. Tenemos productos de diferentes tipos, yla misma acción puede tener diferentes significados para diferentes tipos de productos. Porejemplo, "mostrar" un sonido puede significar reproducirlo, mientras que para otro tipo deproducto puede significar mostrar una imagen guardada en la base de datos. Entoncespodemos utilizar POO y PHP para programar menos y mejor:

Definimos una clase Producto, y los métodos que va a tener (por ejemplo "mostrar"), luegodefinir las clases para distintos tipos de prouctos que extenderán a la clase Producto (claseProdSonido, clase ProdVisible, etc...) sobreescribiendo los métodos que definimos enProducto en cada una de estas nuevas clases para que hagan lo que necesitamos.Deberíamos nombrar las clases de acuerdo con la columna "tipo" que guardamos en la basede datos para cada producto (una tabla típica de productos deberia tener id, tipo, precio,descripción, etc). Luego, podemos recuperar el tipo de producto desde la base de datos einstanciar un objeto de esa clase haciendo :

PHP:

1. <?php2.3. $obj=new $tipo();4. $obj->accion();5.6. ?>

Esta es una característica muy útil de PHP, podremos luego llamar al método "mostrar" de$obj o cualquier otro método sin importar el tipo de objeto que tengamos. Con este tipo detécnica, no es necesario tocar el script que procesa todo, cuando se agregue un nuevo tipode producto, tan solo agregamos la clase que lo maneje. Esta es una técnica muy poderosa,solo definimos los métodos que los objetos deban tener, sin importar el tipo que sea, losimplementamos de diferentes maneras en diferentes clases y los usamos para cualquier tipode objeto en el script principal. Sin ifs, sin 2 programadores en el mismo archivo, felicidadeterna. ¿No están de acuerdo que programar de esta manera es simple, el mantenimiento esmás barato y la reusabilidad se vuelve un hecho ?

Si les toca dirigir un grupo de programadores se vuelve muy sencillo dividir las tareas, cadauno sería responsable por un tipo de objeto y la clase que lo maneja. Lainternacionalización (mismo sitio, diferentes idiomas) puede lograrse utilizando esta técnica,aplicando la clase que sea neceasaria de acuerdo al campo "idioma" que el usuario elija.

Page 9: Programación Orientada a Objetos en PHP

9

Copiando y Clonando

Cuando creamos un objeto $obj, se puede copiar el mismo haciendo $obj2 = $obj, el nuevoobjeto es ahora una copia ( no una referencia ) de $obj así que tiene el mismo estado quetenía $obj en el momento en que la asignación se realizó. Algunas veces no queremos esto,simplemente queremos crear un nuevo objeto de la misma clase que $obj, llamado alconstructor del nuevo objeto como si hubiésemos utilizado la sentencia new. Esto puedelograrse en PHP utilizando serialización y una clase base de la que las demás extienden.

Entrando en terreno peligroso

Cuando serializamos un objeto, obtenemos una cadena con cierto formato, puedesinvestigarlo si eres curioso, una de las cosas que esta cadena contiene es el nombre de laclase (interesante!) y podemos extraerlo haciendo :

PHP:

1. <?php2.3. $cadena = serialize($obj);4. $vec = explode(':',$cadena);5. $nombre = str_replace("\"",'',$vec[2]);6.7. ?>

Asi que supongamos que creamos una clase Universo y forzamos que todas las demásclases extiendan a Universo, podemos definir un método clonar en Universo así:

PHP:

1. <?php2. class Universo3. {4. function clonar()5. {6. $cadena=serialize($this);7. $vec=explode(':',$cadena);8. $nombre=str_replace("\"",'',$vec[2]);9. $ret = new $nombre;10. return $ret;11. }12.}13.14.// Entonces:15.$obj=new Algo();16.//Algo extiende a Universo !!17.$otro = $obj->clonar();18.?>

Page 10: Programación Orientada a Objetos en PHP

10

lo que logramos de esta manera es un nuevo objeto de clase Algo creado de la mismamanera que utilizando new, el contructor es llamado, etc. No estoy muy seguro que esto seaútil para todos, pero la Clase Universo que conoce el nombre de la clase derivada es uninteresante concepto para experimentar. El único límite es la imaginación.

Nota: Para todos los ejemplo, utilicé PHP4. Algunas de los conceptos explicados en esteartículo pueden no funcionar en PHP3.

Referenciahttp://www.zonaphp.com/programacion-orientada-a-objetos-en-php/