You are on page 1of 11

PROGRAMACION ORIENTADA A OBJETOS EN PHP

Este artculo escrito originalmente por Luis Argerich nos introducir a la Programacin Orientada a Objetos (POO o su versin inglesa: OOP) en PHP. En l veremos la forma de programar menos y mejor usando conceptos de POO junto con algunos trucos de PHP. Programacin Orientada a Objetos en PHP Algunos "puristas" afirmarn que PHP no es un verdadero lenguaje orienteado a objetos, lo que es cierto. PHP es un lenguaje hbrido dnde se pueden utilizar POO y programacin 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 ms y ms grandes, el uso de POO puede ayudar, el cdigo POO es fcil de mantener, facl de comprender y fcil de reusar. Y estos son los principios de la Ingeniera de Software. Aplicar estos conceptos en proyectos basados en la web, es la clave para el xito de futurios sitios web. Este artculo es una introduccin a la Programacin 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 programacin 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 Informacin * Herencia * Polimorfismo El encapsulamient o en PHP se logra utilizando clases: Cdigo:
1. 2. 3. 4. <?php class Algo {

// En PHP, las clases usualmente se nombran con la primera le tra en mayscula. 5. var $x; 6. 7. 8. function setX($v)

{ 9. ulas para 10. 11. 12. 13. 14. 15. 16. 17. 18. 19. 20. } ?> } function getX() { return $this->x; } // separar palabras en el nombre del mtodo. // Ejemplo : obtenerRaizCuadrada(); $this->x = $v; // Los Mtodos comienzan en minscula y luego se usan maysc

Por supuesto, cada uno puede utilizar la nomenclatura que desee, pero utilizar una estandarizada es til. Los atributos de los objetos se definen en PHP utilizando la declaracin "var" dentro de la clase, estos atributos no tienen tipo hasta que se les asigna un valor. Un atributo puee ser un entero, un arreglo, un arreglo asociativo o incluso otro objeto. Los mtodos se definen como funciones dentro de la clase, para acceder a los atributos dentro de los mtodos se debe utilizar $this->nombre, de otra manera, se utilizaria una variable local al mtodo. Para crear (instanciar) un nuevo objeto se utiliza el operador new: $obj = new Algo; Luego, se pueden acceder a sus mtodos asi: Cdigo:
1. 2. $obj->setX(5); $valor=$obj->getX();

El mtodo setx le asigna el valor 5 al atributo x en el objeto obj (no a la clase), entonces getx devuelve ese valor: 5 en este caso. En realidad tambin se puede acceder a los atributos del objeto de esta manera: $obj->x = 6; sin embargo esta no es una buena prctica de POO. Yo recomiendo acceder a los atributos definiendo mtodos para asignarlos y devolverlos. Sers un buen programador orientado a objetos si considers los atributos como innacesibles y solo utilizando mtodos para acceder a ellos. Lamentablement e, PHP an no ofrece una manera de

definir un atributo como privado asi que una mala programacin es posible. La Herencia es sencilla de utilizar en PHP con la palabra reservada extend. Cdigo:
1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. } ?> } function getY() { return $this->y; } <?php class Otra extends Algo { var $y; function setY($v) { $this->y = $v;

Objetos de la clase "Otra" ahora poseen todos los atributos y mtodos de la clase padre (Algo) ms sus propios mtodos y atributos. Se puede hacer: Cdigo:
1. 2. 3. $obj2=new Otra; $obj2->setX(6); $obj2->setY(7);

La Herencia mltiple no est soportada por PHP as que no se puede hacer que una clase extienda dos o ms clases diferentes. Se puede sobreescribir un mtodo en la clase derivada tan solo redefinindolo, si redefiniramos getx en "Otra" ya no podramos acceder al metodo getx en "Algo". Si se declara un atributo en una clase derivada con el mismo nombre de un atributo de la clase base, el atributo derivado "esconde" al atributo de la clase base cuando se intenta acceder al mismo. Se puedden definir Constructores en las clases. Los Constructores son mtodos con el

mismo nombre de la clase y que son llamados en el momento en que se instancia un objeto, por ejemplo: Cdigo:
1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. 19. 20. 21. } ?> } function getX() { return $this->x; } function setX($v) { $this->x=$v; } function Algo($y) { $this->x=$y; <?php class Algo { var $x;

Asi que ahora se puede crear al objeto asi : $obj=new Algo(6); Y el Constructor automticamente asigna 6 al atributo x. Los Constructores y los mtodos son funciones normales de PHP, por lo que se pueden usar argumentos por defecto. function Algo($x="3",$y="5") Entonces:

Cdigo:
1. 2. 3. 4. 5. <?php $obj=new Algo(); // x=3 e y=5 $obj=new Algo(8); // x=8 e y=5 $obj=new Algo(8,9); // x=8 e y=9 ?>

Los argumentos por defecto son utilizandos de la misma manera que en C++, asi que no es posible pasarle un valor a Y dejando que X tome el valor por defecto, los argumentos son asignados de izquierda a derecha y cuando no se encuentran ms argumentos, y si la funcin esperaba ms de los que se enviaron, entonces los restantes toman sus valores por defecto. Cuando un objeto de una clase derivada es instanciado, solo su Constructor es llamado, pero no el de la clase Padre, esto es una lstima porque el encadenamiento de constructores es una caracterstica clsica de la POO. Si quieres llamar al constructor de la clase base, se tiene que hacer explicitamente en el constructor de la clase derivada. Esto funciona porque todos los metodos de la clase padre estn disponibles en la clase derivada debido a la Herencia. Cdigo:
1. 2. 3. 4. 5. clase padre. 6. } 7. ?> <?php function Otra() { $this->y=5; $this->Algo(); //llamada explicita al contructor de la

Un mecanismo interesante en la POO es la utilizacin de Clases Abstractas, estas clases no son instanciables y su nico propsito es el de definir una interfase para sus clases derivadas. Los diseadores y analistas generalmente utilizan Clases Abstractas para forzar a los programadores a derivar clases de ciertas clases base, y de esa manera asegurarse que las nuevas clases tendrn ciertas funcionalidade s deseadas. No existe una manera estandar de hacer esto en PHP, pero: Si necesitas esta funcionaliad, define la clase base y coloca un "die();" en su constructor, de esta manera nos aseguramos que la clase no es instanciable, luego define sus mtodos (interfase) colocando "die()" al final de cada uno, de esa manera, si un programador no sobreescribe el mtodo entonces ocurre un error. Incluso puede ser necesario estar seguro que una clase es derivada de una clase base en particular,

entonces es recomendable agregar un mtodo en la clase base que la identifique (que retorne algun "identificador") y verificar esto cada vez que se recibe un objeto como argumento. Por supuesto esto no funciona si el diablico programador sobreescribe el mtodo en la clase derivada, pero generalmente el problema es tratar con programadores holgazanes, no con programadores diablicos! Por supuesto, es mejor mantener la clase base fuera del alcance de los programadores, tan solo presentarles la interfase y hacerlos trabajar. No hay destructores en PHP. La "Sobrecarga" ( que es diferente a la "Sobreescritura" ) no es soportada por PHP. En POO uno "sobrecarga" un mtodo cuando se definen dos o tres mtodos con el mismo nombre, pero con diferentes nmeros o tipos de parmetros (dependiendo del lenguaje). No existen tipos de datos en PHP, as que sobrecargar por tipos de datos no funciona, sin embargo, sobrecargar por cantidad de parmetros tampoco existe. Es muy til a veces en POO sobrecargar los Constructores para poder instanciar el objeto de diferentes maneras (pasndole diferentes nmeros de parmetros). Un truco para hacer esto en PHP es: Cdigo:
1. 2. 3. 4. 5. 6. 7. 8. a mal 9. del 10. 11. 12. 13. 14. 15. 16. 17. } function MiClase2($x,$y) function MiClase1($x) { //cdigo; } // mtodo que se va a llamar <?php class MiClase { function MiClase() { $nombre="MiClase".func_num_args(); $this->$nombre(); // Notar que $this->nombre(); generalmente estar // pero aqui $nombre es un string con el nombre

18. 19. 20. 21. 22. } ?> } { //cdigo;

Con este "trabajo extra" en la clase, el uso de la misma se vuelve transparente al usuario ( de la clase, no del sitio ) : Cdigo:
1. 2. 3. 4. <?php $obj1=new MiClase('1'); // llamar a MiClase1 $obj2=new MiClase('1','2'); // llamar a MiClase2 ?>

Muchas veces esto es muy til. Polimorfismo Polimorfismo se define a la habilidad de un objeto de determinar que mtodo invocar para un objeto pasado como argumento en tiempo de ejecucin. Por ejemplo, si tenemos una clase "Figura" que define un mtodo para dibujar y dos clases derivadas Crculo y Rectngulo dnde se sobreescriben ese mtodo, se puede tener un mtodo que espere un argumento "x" y luego hacer $x->dibujar(). Si tuvieramos polimorfismo, el mtodo "dibujar" llamado dependera del tipo de objeto que se le pasa a la funcin. El Polimorfismo es muy sencillo y hasta natural en lenguajes interpretados como PHP. Asi que afortunadament e PHP soporta Polimorfismo. Cdigo:
1. 2. 3. 4. a" 5. 6. 7. 8. 9. $obj=new Crculo(3,187); $obj2=new Rectngulo(4,5); } <?php function dibujar($x) { // Supongamos que este es un mtodo de una clase "Pizarr $x->dibujar();

10. 11. ulo. 12. $pizarra->dibujar($obj); // llamar al mtodo dibujar de Crc // llamar al mtodo dibujar de Rect

$pizarra->dibujar($obj2); ngulo. 13. ?>

Tcnicas avanzadas de POO en PHP Luego de aprender los conceptos bsicos de la POO, les puedo mostrar algunas tcnicas ms avanzadas: Serializacin PHP no soporta Objetos Persistentes. En POO los Objetos Persistentes son aquellos que mantienen su estado y funcionalidad a travs de mltiples invocaciones de la aplicacin, esto es, la habilidad de "grabar" el objeto a un archivo o base de datos y luego "cargarlo" nuevamente. Este mecanismo es conocido como Serializacin. PHP tiene una funcin de serializacin que puede ser utilizada con objetos, y devuelve una cadena que representa a ese objeto. Sin embargo la serializacin guarda los atributos pero no los mtodos. En PHP4, si uno serializa un objeto hacia una cadena $s, luego se destruye el objeto y luego se vuelve a des-serializar el objeto hacia $obj, an se puede tener acceso a los mtodos! Yo en realidad no recomiendo esto porque (a) La documentacin no garantiza este funcionamiento y en futuras versiones de PHP puede dejar de existir. (b) Esto puede llevar a crear "ilusiones" de grabar el objeto serializado en una cadena y salir del script. En futuras ejecuciones del script, no podrs des-serializar la cadena hacia un objeto y esperar que los mtodos estn alli, porque la cadena que representa al objeto no guarda los mtodos del mismo. Resumiendo, la serializacin en PHP es MUY til para guardar los atributos de un objeto, pero solo eso. (Tambin se pueden serializar arreglos simples y asociativos para guardarlos en disco). Ejemplo Cdigo:
1. 2. 3. 4. 5. 6. 7. //...algunas miles de instrucciones despus.... <?php $obj=new ClaseFoo(); $cadena=serialize($obj); // Grabamos $cadena a disco

8. 9. 10. //Cargamos $cadena del disco $obj2 = unserialize($cadena); ?>

Obtendremos los atributos pero no los mtodos (de acuerdo a la documentacin). Esto nos lleva a que sea $obj2->x la nica manera de acceder a los atributos (ya que no tenemos mtodos 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 artculo. Serializacin Completa es una caracterstica que apreciara mucho en futuras versiones de PHP. Utilizando Clases para trabajar con datos almacenados Una de las mejores cosas de la POO y PHP es que se pueden definir sencillamente clases para manipular ciertas cosas y luego llamar a las clases apropiadas cuando sea necesiario. Supongamos que tenemos un formulario HTML dnde el usuario elige un producto, enviando su ID de producto, nosotros tenemos esa informacin en una base de datos y queremos mostrar por pantalla su precio, etc, etc. Tenemos productos de diferentes tipos, y la misma accin puede tener diferentes significados para diferentes tipos de productos. Por ejemplo, "mostrar" un sonido puede significar reproducirlo, mientras que para otro tipo de producto puede significar mostrar una imagen guardada en la base de datos. Entonces podemos utilizar POO y PHP para programar menos y mejor: Definimos una clase Producto, y los mtodos que va a tener (por ejemplo "mostrar"), luego definir las clases para distintos tipos de prouctos que extendern a la clase Producto (clase ProdSonido, clase ProdVisible, etc...) sobreescribien do los mtodos que definimos en Producto en cada una de estas nuevas clases para que hagan lo que necesitamos. Deberamos nombrar las clases de acuerdo con la columna "tipo" que guardamos en la base de datos para cada producto (una tabla tpica de productos deberia tener id, tipo, precio, descripcin, etc). Luego, podemos recuperar el tipo de producto desde la base de datos e instanciar un objeto de esa clase haciendo : Cdigo:
1. 2. 3. 4. 5. 6. ?> $obj=new $tipo(); $obj->accion(); <?php

Esta es una caracterstica muy til de PHP, podremos luego llamar al mtodo "mostrar" de $obj o cualquier otro mtodo sin importar el tipo de objeto que tengamos. Con este tipo de tcnica, no es necesario tocar el script que procesa todo, cuando se agregue un nuevo tipo de producto, tan solo agregamos la clase que lo maneje. Esta es una tcnica muy poderosa, solo definimos los mtodos que los objetos deban tener, sin importar el tipo que sea, los implementamos de diferentes maneras en diferentes clases y los usamos para cualquier tipo de objeto en el script principal. Sin ifs, sin 2 programadores en el mismo archivo, felicidad eterna. No estn de acuerdo que programar de esta manera es simple, el mantenimiento es ms barato y la reusabilidad se vuelve un hecho ? Si les toca dirigir un grupo de programadores se vuelve muy sencillo dividir las tareas, cada uno sera responsable por un tipo de objeto y la clase que lo maneja. La internacionali zacin (mismo sitio, diferentes idiomas) puede lograrse utilizando esta tcnica, aplicando la clase que sea neceasaria de acuerdo al campo "idioma" que el usuario elija. Copiando y Clonando Cuando creamos un objeto $obj, se puede copiar el mismo haciendo $obj2 = $obj, el nuevo objeto es ahora una copia ( no una referencia ) de $obj as que tiene el mismo estado que tena $obj en el momento en que la asignacin se realiz. Algunas veces no queremos esto, simplemente queremos crear un nuevo objeto de la misma clase que $obj, llamado al constructor del nuevo objeto como si hubisemos utilizado la sentencia new. Esto puede lograrse en PHP utilizando serializacin y una clase base de la que las dems extienden. Entrando en terreno peligroso Cuando serializamos un objeto, obtenemos una cadena con cierto formato, puedes investigarlo si eres curioso, una de las cosas que esta cadena contiene es el nombre de la clase (interesante!) y podemos extraerlo haciendo : Cdigo:
1. 2. 3. 4. 5. 6. 7. ?> $cadena = serialize($obj); $vec = explode(':',$cadena); $nombre = str_replace("\"",'',$vec[2]); <?php

Asi que supongamos que creamos una clase Universo y forzamos que todas las dems clases extiendan a Universo, podemos definir un mtodo clonar en Universo asi :

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

lo que logramos de esta manera es un nuevo objeto de clase Algo creado de la misma manera 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 un interesante concepto para experimentar. El nico lmite es la imaginacin. Nota: Para todos los ejemplo, utilic PHP4. Algunas de los conceptos explicados en este artculo pueden no funcionar en PHP3. EXTRADO DE:: http://www.zonaphp.com

You might also like