Objetos en PHP (Primera parte) Objetivos Dar a conocer los fundamentos de la Programación Orientada a Objetos. Tener claridad en cuanto al objetivo de utilizar el enfoque orientado a objetos de PHP. Identificar las diferencias fundamentales entre la Programación Orientada a Objetos y la programación funcional. Utilizar conceptos como abstracción de clases, polimorfismo e interfaces para resolver problemas prácticos. Programar utilizando clases y objetos con PHP. Contenido 1. Introducción a la Programación Orientada a Objetos. 2. Fundamentos de la Programación Orientada a Objetos 3. Clases y objetos 4. Constructores y destructores 5. Diferencias en la creación de clases con PHP4 y PHP5 6. Control o nivel de acceso a los miembros de una clase 7. Definición de constantes en los objetos 8. Propiedades y métodos estáticos 9. Clonación de objetos 10. Autocarga de objetos Contenido 11. Sobrecarga de propiedades y métodos. 12. Herencia. 13. Clases y métodos finales. 14. Clases y métodos abstractos. 15. Polimorfismo. 16. Interfaces. 17. Manejo de excepciones. Introducción a la POO Hasta este punto en el curso, hemos desarrollado secuencias de comando en PHP con instrucciones secuenciales que utilizan estructuras de control y en las últimas clases con funciones que permiten desarrollar pequeños módulos de programa que pueden ser invocados desde el flujo principal del programa o desde otras funciones. Introducción a la POO Este enfoque de programación es conocido como programación estructurada o, de acuerdo a su evolución histórica, como programación modular, en donde un programa demasiado complejo es dividido en módulos o subprogramas más legibles o manejables. La Programación Orientada a Objetos es un paradigma de programación que viene a sustituir el enfoque de la programación modular ofreciendo muchas más ventajas. Este nuevo paradigma de programación se basa en conceptos como herencia, abstracción, polimorfismo, encapsulamiento, entre otros. Introducción a la POO PHP inició como un lenguaje de scripts (secuencias de comando o guiones) del lado del servidor útil para construir páginas web personales sencillas. A medida que se iban lanzando nuevas versiones se fueron incluyendo algunas características que permitieron programar aplicando orientación a objetos, sobre todo en la versión 4.0. Sin embargo, fue hasta la versión 5.0 que se presentó al mundo de los desarrolladores como una verdadera plataforma de programación orientada a objetos, gracias al motor Zend 2.0. Fundamentos de la POO (I) Se considera a la Programación Orientada a Objetos (POO) como un método de desarrollo de software en el que se identifican las características y los comportamientos de los elementos, reales o abstractos, para modelarlos haciendo uso de clases y objetos. En la POO la creación de programas se basa en la definición de clases que constituyen modelos del mundo real y a partir de las cuales se crean objetos. Fundamentos de la POO (II) Una clase es una descripción genérica, también llamada modelo o plantilla. Esta clase es tomada de un objeto del mundo real y modelada a través de propiedades y métodos. Un objeto es una instancia, muestra o ejemplar de la clase que posee dos características importantes que son: el estado y el comportamiento. La relación que existe entre clase y objeto, viene a ser la misma que hay entre el diseño de un automóvil (esta sería la clase o modelo) y el automóvil concreto construido en base a ese modelo, ya con un color específico, un número de puertas concreto, un tamaño de motor, etc. Fundamentos de la POO (III) El estado de un objeto se define mediante un conjunto de propiedades o atributos del objeto en sí, que son las características o información que define o contiene el objeto en cuestión. El comportamiento se indica mediante métodos, que son las funciones, operaciones o acciones que se pueden realizar con las propiedades o atributos del objeto, ya sea para modificar su comportamiento o para obtener algún efecto externo. Esto significa que el objeto puede realizar ciertas tareas mediante el envío de mensajes. Fundamentos de la POO (IV) Fundamentos de la POO (V) Fundamentos de la POO (VI) Fundamentos de la POO (VI) En conclusión, cuando se desarrollan aplicaciones orientadas a objetos, se crearán objetos a partir de cualquier elemento o concepto, pudiendo ser estos objetos físicos como una mesa, un carro, una cuenta bancaria o un cliente, o un objeto conceptual que solo existe a nivel de software, como un archivo, un formulario o página web. Los objetos encapsulan tanto propiedades como métodos. Las propiedades se utilizan para almacenar información de estado del objeto, en tanto que los métodos se ocupan de hacer modificaciones sobre dicho estado, definiendo así el comportamiento del mismo. Fundamentos de la POO (VIII) El software orientado a objetos se diseña y construye como un conjunto de objetos independientes con atributos o propiedades y operaciones o métodos que interactúan para realizar las tareas que sean requeridas. La ventaja principal del software orientado a objetos es su capacidad de fomentar la encapsulación, también conocida como ocultación de datos. Esto significa que el acceso a las propiedades de un objeto, solamente es posible hacerlo a través de sus métodos. Ilustración de clase y objeto (I) Ilustración de clase y objeto (II) Ilustración de clase y objeto (III) Ilustración de clase y objeto (IV) Estructura de una clase en PHP (I) Para crear una clase en PHP, debe utilizar la palabra clave class y seguir la siguiente estructura sintáctica general: class nombreClase [extends parentClass]{ //propiedades; [public|private|protected] $property1; … //métodos; [public|private|protected] function name([$arg1,…]){} } Estructura de una clase en PHP 4.0 (II) class nombreClase { //Propiedades var $propiedad1; var $propiedad2; var $propiedad3; … var $propiedadN; //Métodos function metodo1(){//instrucciones1;} function metodo2(){//instrucciones2;} function metodo3(){//instrucciones3;} … function metodoN(){//instruccionesN;} } Estructura de una clase en PHP 5.0 (III) class nombreClase { //Propiedades private|public|protected $propiedad1; private|public|protected $propiedad2; private|public|protected $propiedad3; … private|public|protected $propiedadN; //Métodos function metodo1([arg1[,arg2,…]]){//instrucciones1;} function metodo2([arg1[,arg2,…]]){//instrucciones2;} function metodo3([arg1[,arg2,…]]){//instrucciones3;} … function metodoN([arg1[,arg2,…]]){//instruccionesN;} } Clases y objetos en PHP (I) Una clase básica en PHP se puede representar utilizando un esquema de bloque como el siguiente: Clase persona Propiedades
Nombre $nombre
Apellido $apellido
Edad $edad
Métodos
Poner nombre asignar_nombre($nombre, $apellido)
Dar nombre completo dar_nombre_completo()
Clases y objetos en PHP (II) Implementando en código PHP la clase anterior: class persona { //Propiedades private $nombre; private $apellido; private $edad; //Métodos function asignar_nombre($nombre,$apellido){ $this->nombre = $nombre; $this->apellido = $apellido; } function dar_nombre_completo(){ return $this->nombre . "" . $this->apellido; } } Creación de objetos La creación de ejemplares de la clase es a lo que se le denomina instanciar a un objeto de la clase: $persona1 = new persona(); //crea una instancia $persona1 -> asignar_nombre("Raul","López"); $persona1 -> dar_nombre_completo();
La primera instrucción crea una instancia de la clase persona; es decir,
un objeto concreto o una persona concreta. Se utiliza la palabra reservada new para crear dicha instancia. La segunda y la tercera instrucción invocan los métodos del objeto persona. El método asignarnombre() asigna el nombre enviado a la persona y el método darnombre() muestra el nombre asignado a esta persona en la salida. Es importante comprender que el orden en que se invoquen estos métodos es relevante para obtener el resultado esperado. Constructores y destructores (I) Un constructor es un método que se ejecuta automáticamente cuando se crea un ejemplar del objeto, sin necesidad de que sea invocado. Esto resulta muy útil si se desea que las propiedades del objeto posean un conjunto de características por defecto o, ejecutar una serie de acciones previas, conocidas como inicialización del objeto. Un nuevo objeto se crea en el momento en que se ejecuta la instrucción con la palabra reservada new seguida del nombre de la clase acompañado de unos paréntesis. Esta era la forma de hacerlo en PHP 4.0. Para PHP 5.0 se modificó completamente la implementación de la POO, definiendo como constructor el método especial __construct(). Constructores y destructores Los constructores de PHP 5.0 o superior se declaran utilizando el método especial __construct(). Este es uno de los cambios en la versión 5.0 con respecto a la versión 4.0 de PHP. En la versión 4.0 los nombres de los constructores tenían el mismo nombre de la clase. Por motivos de compatibilidad inversa, si en una clase no se encuentra una función con el nombre __construct(), PHP buscará una función que tenga el mismo nombre que la clase. Ejemplo de constructor En el ejemplo de la clase persona, se crea un nuevo objeto cuando se ejecuta la siguiente instrucción: $juan = new persona(); Se ejecuta un constructor por defecto o un constructor definido por el programador dentro de la clase. En PHP 4 los constructores se crean mediante una función con el mismo nombre de la clase. PHP 4 no dispone de destructores. En PHP 5 se incorpora una función constructora unificada denominada __construct(), que puede o no llevar parámetros. Los constructores no devuelven valores. Destructor PHP 5 incorpora el destructor, algo que no existía en las versiones de la generación 4. La utilidad de un destructor en PHP es limitada, ya que PHP siempre libera los recursos utilizados al finalizar la ejecución del script. Un apunte importante en cuanto al constructor y destructor, es que cuando se implementa un constructor o destructor en una clase hija, el constructor de la clase padre ya no puede ser invocado de forma directa e inmediata. Destructor Para llamar al constructor de una clase padre, si se ha redefinido un constructor en la clase hija, debe emplear una instrucción como la siguiente: parent::__construct(); parent::__destruct();
El destructor de un objeto se llama justo antes de
eliminar el objeto. Esto puede suceder en dos casos: Porque han desaparecido todas las referencias al objeto por haber utilizado la función unset() en el objeto. Porque el script ha terminado, ya sea de forma natural o porque se ha producido algún tipo de error. Ejemplo de destructor <?php class person { public function save(){ echo "Salvando los datos en la base de datos."; } public function __destruct(){ $this->save(); } } //Creando un objeto persona $persona = new person(); unset($persona); $otrapersona = new person(); die("Hemos finalizado el script de forma forzada"); ?> Diferencias entre PHP 4 y PHP 5 en cuanto a creación de objetos (I) La primera gran diferencia es que el modelo de objetos en PHP 5 ha sido completamente reescrito lo cual ha permitido mejorar el desempeño e incorporar muchísimas más características. En PHP 4 cuando se crean nuevos objetos con la sentencia new se devuelve el objeto mismo y no una referencia a este. PHP 4 únicamente disponía de constructores, no de destructores. PHP 5 incorpora ambos conceptos. Diferencias entre PHP 4 y PHP 5 en cuanto a creación de objetos (II) En PHP 4 los constructores debían tener el mismo nombre que la clase. PHP 5 ha incorporado los métodos unificados __construct(), como constructor, y __desctruct(), como destructor. PHP 4 no daba soporte para el control de acceso de las propiedades de un objeto. PHP 5 incorpora las palabras reservadas private, protected y public, al igual que los lenguajes orientados a objetos más reconocidos, para definir el control de acceso a los miembros de una clase. Creación de objetos en PHP 4 y PHP 5 $obj = new clase(); En PHP 4: $obj En una instrucción como: p1; $objx = $obj p2; m1(); En PHP 4 se crea una copia en un objeto totalmente independiente, • En PHP 5: $obj mientras que en PHP 5 el nuevo objeto p1; p2; es una referencia que apunta, al igual m1(); que el objeto original, al objeto en sí. Niveles de acceso a los miembros de una clase (I) PHP proporciona tres niveles de acceso para los miembros declarados en una clase: 1. Público (public). 2. Privado (private). 3. Protegido (protected). Niveles de acceso a los miembros de una clase (II) public: significa que el miembro de la clase es público y que, por tanto, se puede acceder a este desde cualquier parte del script. Estos miembros pueden llamarse o modificarse internamente dentro del objeto o fuera de este. private: a estos miembros de clase sólo se puede acceder desde dentro de una instancia de dicha clase utilizando la palabra reservada $this, que hace referencia al objeto mismo, seguido del operador de instancia de objeto -> y, a continuación el nombre de la propiedad. protected: es similar a private, con la diferencia de que además de la instancia de la clase, también puede tener acceso a este miembro cualquier clase hija. Niveles de acceso a los miembros de una clase (III) En PHP 4 no existía el concepto de nivel de acceso y, por defecto, todas las propiedades eran públicas. Para definir las propiedades se hacía uso de la palabra reservada var. Con PHP 5 se incorporaron los niveles de acceso por lo que ahora si se pueden establecer miembros privados (private) y protegidos (protected), además de miembros públicos (public). Los que ya tienen mucha experiencia en programación acostumbran a crear clases donde las propiedades son declaradas con ámbito privado, mientras que los métodos se declaran con ámbito público. Niveles de acceso a los miembros de una clase (IV) Ejemplo con propiedades privadas y métodos públicos: class celda { private $colorfondo; function ponercolorfondo($color){ if($color=='Orange' || $color=='Red' || $color=='Maroon'){ $this->colorfondo = $color; } else{ die("ERROR: No se permite ".$color." como color de fondo"); } } } $fila = new celda(); //$fila->colorfondo = 'fuchsia'; //provocará un error fatal $fila->ponercolorfondo('orange'); Definición de constantes en las clases (I) Esta es una nueva característica de PHP 5 que permite definir valores constantes dentro de una clase. Para definir una constante dentro de la clase se utiliza la palabra reservada const seguida por el identificador de la constante a definir y el valor asignado. Ejemplo: const PI = 3.1415926535 Definición de constantes en las clases (II) A este valor constante se puede acceder desde cualquier parte de la clase anteponiendo la palabra reservada self seguida del operador de resolución de contexto (::) y, a continuación, del identificador de la constante. Sin embargo, para acceder a este valor desde fuera del ámbito de la clase debe hacer uso del nombre de la clase junto con el operador de resolución (::), seguido por el identificador de la constante. echo constAreas::PI; Propiedades y métodos estáticos (I) Una propiedad o método estático pertenece a la clase en la que está definida(o), no a los objetos creados a partir de esa clase. Lo anterior significa que estos atributos y métodos pueden utilizarse directamente desde la clase, sin necesidad de crear un objeto. Sin embargo, una propiedad o método estático puede ser llamado desde fuera del contexto de un objeto. La declaración de una propiedad o método de este tipo se realiza empleando la palabra reservada static que debe colocarse justo después de la declaración de visibilidad (public, private o protected) en caso de que esta exista. Propiedades y métodos estáticos (II) El hecho que las propiedades y métodos estáticos pertenezcan a la clase y no a los objetos, hace que para poder acceder a estas sea necesario utilizar el nombre de clase reservado: self y, a continuación, el operador de resolución de ámbito "::". self permite hacer referencia a la clase actual en la que se encuentra. Se utiliza principalmente para acceder a propiedades y métodos estáticos, así como a constantes de la propia clase. class empleado { private static $idempleado = 0; private $nombre; private $apellido; public __construct($nombre, $apellido){ self::$idempleado++; $this->nombre = $nombre; $this->apellido = $apellido; } } Clonación de objetos (I) En PHP 4, cuando un objeto se asigna a una variable, se crea una copia exacta del objeto; es decir, se hace una copia de dicho objeto y los cambios que se hacen sobre las propiedades de este objeto sólo afectan a la copia. Este comportamiento no se ajusta muchas veces a lo que se desea hacer, ni a la forma en que la mayoría de lenguajes orientados a objeto abordan este problema. En PHP 5 cuando se asigna un objeto a otro objeto directamente, siempre se estará creando una referencia al objeto original, de modo que siempre que se haga alguna modificación en una propiedad, se estará alterando la propiedad en ambos objetos. <?php $unaPersona = new persona(); $otraPersona = $unaPersona; ?> Clonación de objetos (II) En el ejemplo anterior tanto $unaPersona como $otraPersona representan el mismo objeto. De modo que, cualquier modificación realizada en una de las instancias del objeto afectará también a la otra. En PHP 5 para crear una copia exacta del objeto en una instancia completamente independiente, debe utilizar la palabra reservada clone. Esta palabra llama al método __clone() del objeto. Este método no puede ser llamado directamente. $unaPersona = new persona(); $otraPersona = clone $unaPersona; Auto carga de objetos en PHP (I) Es habitual que muchos programadores creen un script PHP por cada definición de clase que realicen. Esto implica después, tener que incluir una larga lista de sentencias include o require necesarias al inicio del script para poder utilizar las clases definidas. PHP 5 evita esta molestia definiendo una función __autoload() la cual es llamada automáticamente en caso que se intente utilizar una clase que no ha sido definida aún en la secuencia de comandos. Al llamarse a esta función PHP da una última oportunidad al script de cargar la clase antes de interrumpirse y enviar un error fatal. Auto carga de objetos en PHP (II) Ejemplo: <?php //Definición de la función de autocarga function __autoload($class_name){ require_once $class_name . ".php"; //o ".inc.php" } //Intento de crear objetos de una clase que //aún no se ha definido en el script $obj = new MyClass1(); $objalt = new MyClass2(); ?> En el ejemplo anterior, el script intentará cargar las clases MyClass1 y MyClass2 desde los archivos MyClass1.php y MyClass2.php, respectivamente, antes de interrumpir con un error fatal el script. FIN (1a parte) Lenguajes Interpretados en el Servidor Objetos en PHP (Segunda parte) Sobrecarga La sobrecarga de propiedades y métodos en PHP se lleva a cabo por medio de los métodos especiales __get(), __set() y __call(). Los métodos __get() y __set() son invocados de forma automática cuando se intenta acceder a una propiedad o método inexistente en el objeto. __set(), permite establecer un valor para una propiedad, __get(), permite recuperar u obtener el valor de la propiedad, mientras que __call(), permite, además del acceso a métodos no definidos en el objeto, implementar la sobrecarga de métodos. Sobrecarga de miembros Los miembros de una clase pueden ser sobrecargados utilizando los métodos __set() y __get(). La sintaxis de estos métodos es la siguiente: void __set(string $name, mixed $value); mixed __get(string $name); En donde, $name es el nombre de la propiedad que debe ser asignada (set) u obtenida (get). $value es el valor que se intenta establecer (set) al miembro no existente del objeto. Los métodos __set() y __get() son llamados únicamente si la propiedad referenciada no existe en el objeto. El uso del método __get(), supone una ejecución previa de __set() para poder acceder a una propiedad que no ha sido definida en el objeto. Sobrecarga de métodos Para implementar la sobrecarga de métodos se utiliza el método __call(), diseñado para tener acceso a métodos no definidos para el objeto. La sintaxis de este método es la siguiente: mixed __call(string $name, array $arguments);
En donde, $name, es el nombre del método invocado que no está
definido, y $arguments contiene los argumentos que serán pasados al método en una matriz. Utilizar __call() para implementar la sobrecarga es viable en PHP, sin embargo, debe recordar que en PHP los argumentos pueden tomar cualquier tipo de dato válido y que, además, PHP soporta lista de argumentos de longitud variable. Por tal razón, puede que no sea tan útil esta función. Ejemplo de sobrecarga class sinPropiedades { function __set($propiedad, $valor){ echo "Asignamos $valor a $propiedad"; $this->propiedad = $valor; } function __get($propiedad){ echo "Acceso a la propiedad $propiedad(clase ", __CLASS__,")\n"; return $this->propiedad; } function __call($metodo, $parametros){ echo "Acceso al método $metodo (clase", __CLASS__, ")\nArgumentos:\n", var_dump($parametros), "\n"; } } //Fin clase sinPropiedades Ejemplo de sobrecarga //Creación de un nuevo objeto sinPropiedades $obj = new sinPropiedades(); //Asignando valores a dos propiedades no definidas $obj->nombre = "Sergio"; $obj->edad = 25; //Hacer un volcado del objeto echo var_dump($obj), "\n"; //Acceder a las propiedades sobrecargadas y a otra inexistente echo 'Nombre: ', $obj->nombre, "\n"; echo 'Edad: ', $obj->edad, "\n"; echo 'Apellido: ', @$obj->apellido, "\n"; //Intentar ejecutar un método inexistente echo $obj->darNombre('Sergio', 'Pérez', 30); Herencia de clases (derivación) El concepto de herencia en POO es la relación que se da entre dos clases por la cual la clase denominada hija, subclase o clase derivada, además de contar con sus propias propiedades y métodos, tiene a disposición, por herencia, los miembros definidos en la clase denominada clase padre o superclase. Herencia de clases (derivación) Los lenguajes de programación orientados a objetos permiten definir clases en términos de otras clases y PHP no es la excepción. De modo que si se define una clase persona con propiedades evidentes como el nombre, sexo, edad, estado civil, estatura, peso, etc. Y métodos como despertar, comer, caminar, dormir, etc, es factible definir clases derivadas o subclases como empleado, estudiante, trabajador a partir de aquélla. Por otra parte, la clase persona es clase padre o superclase de las clases empleado, estudiante y trabajador. Herencia de clases (derivación) El propósito principal de la herencia es la reutilización del código, definiendo clases en términos de otras clases. Una clase hija puede volver a definir uno, alguno o todos los métodos, propiedades y constantes de la superclase para proporcionar una funcionalidad adicional o diferente. Herencia de clases (derivación) Si se ha redefinido una propiedad o método de la clase padre en la clase hija, siempre es posible acceder a las propiedades o métodos de la clase padre, haciendo uso de la palabra reservada parent. Acceder a una propiedad de la clase padre que ya fue redefinida en la clase hija: parent::property; Acceder a un método de la clase padre que ya fue redefinido en la clase hija: parent::method(); Herencia de clases (derivación) Ejemplo de herencia (I) Intentaremos explicar la herencia con un caso particular. Imaginemos un objeto archivo. Para nosotros un archivo es un conjunto de bytes almacenados de alguna forma en el disco fijo de una computadora, que posee un cierto número de características, entre ellas: el nombre, la extensión, el tamaño en bytes, el propietario, los permisos de acceso, la fecha de creación y la de modificación. Las acciones que se pueden realizar con archivos son, entre otras: copiarlo, renombrarlo, borrarlo, etc. Ejemplo de herencia (II) Los tipos de archivo pueden ser muy diversos. Se puede tratar de un archivo de texto en caracteres ASCII, una imagen en formato GIF, JPG o PNG, un archivo de audio como mp3, wma, una película en formato DivX, MPEG, AVI, etc. Podemos imaginarnos este ejemplo en un esquema o diagrama de jerarquía, como se ilustra: Ejemplo de herencia (III)
Archivo
Archivo Archivo de Archivo de
gráfico audio vídeo
Formato Formato Formato Formato Formato AVI MPEG
PNG JPG GIF mp3 WMA Clases y métodos finales (I) Las clases y métodos finales proporcionan al desarrollador un mecanismo de control sobre la herencia. Las propiedades, métodos y clases que se declaran como finales evitan que se pueda sobrecargar la clase, que se implemente un método de la clase padre en cualquier clase derivada o que se vuelva a definir una propiedad de la clase padre, también en sus clases derivadas. Para este propósito, sólo debe anteponerse la palabra reservada final al nombre de la clase, a la palabra reservada function o al nombre de la propiedad. Clases y métodos finales (II) Una clase declarada como final no puede tener subclases: final class archivoPDF{ public function crearPDF(){//Lógica de la función} } Un método que se declara como final dentro de una clase, puede ser utilizado por las subclases o clases heredadas, pero no puede ser sobrescrito por estas. Esto significa que no puede volver a implementarse en las subclases. class archivoMP3{ final public function playMP3(){//Lógica de la función} } Clases y métodos finales (III) Intentar derivar una clase que ya fue declarada con final producirá un error fatal que interrumpirá la secuencia de comandos PHP. Del mismo modo, si dentro de una clase derivada se intenta implementar un método que ya fue declarado como final dentro de su clase padre, también producirá un error fatal. Clases y métodos finales (IV) Ejemplo class computer{ private $serial_number; final function setSerialNumber($serial_number){ $this->serial_number = $serial_number; } } class laptop extends computer{ private $new_serial_number; //Redefiniendo el método setSerialNumber() en la clase derivada function setSerialNumber($new_serial_number){ $this->new_serial_number = $new_serial_number; } } //Probando $portable = new laptop(); //Cuando se intente ejecutar esta instrucción se arrojará un error fatal $portable->setSerialNumber("1234aBCd"); Clases abstractas (I) Otro de los recursos que proporciona mayor control sobre el proceso de herencia son las clases y métodos abstractos. Es común que encontremos situaciones donde una clase represente un concepto abstracto y, como tal, no debería ser posible concretarlo. De modo similar, en términos de programación orientada a objetos, tendría que ser posible modelar un concepto abstracto sobre el que no sea posible la creación de instancias del mismo. Clases abstractas (II) Esto significa que estas clases representarán conceptos abstractos que no pueden concretarse mediante instancias. Lo anterior significa, que como desarrolladores deberíamos poder modelar objetos abstractos impidiendo que se puedan crear instancias del mismo. Podemos entender mejor la abstracción, pensando en un concepto de la vida real como la comida. Todos sabemos lo que es la comida, pero ¿la hemos visto alguna vez?. Lo que si hemos visto es algún plato de pollo, carne, arroz, frijoles, etc. Clases abstractas (III) Sin embargo, el concepto de comida es, en si mismo, un concepto abstracto. Existe sólo como una generalización de cosas más específicas. Lo mismo sucede con conceptos como bebidas, postres, medicinas, etc. Clases abstractas (IV) La característica principal de una clase abstracta es que no puede ser instanciada. Una clase abstracta es utilizada en Programación Orientada a Objetos para crear objetos abstractos. Una clase abstracta es diseñada para proporcionar una super clase que representa un objeto abstracto que no puede ser concretado. Clases abstractas (V) Para crear una clase abstracta en PHP debe anteponerse la palabra reservada abstract delante de la palabra, también reservada, class. Una clase abstracta, además de declarar e implementar propiedades y métodos, puede definir también métodos abstractos. Los métodos abstractos no se implementan (no contienen código alguno). Estos métodos deben ser implementados en las clases hijas o derivadas. También, es posible que en la clase hija, el método siga declarándose abstracto. Si esto ocurre la implementación de la clase podría realizarse en el siguiente nivel jerárquico. Clases abstractas (VI) <?php abstract class number { private $value; abstract public function value(); public function reset(){ $this->value = NULL; } } //Clase que implementa el método abstracto class integer extends number { private $value; public function value(){ return (int)$this->value; } } $entero = new integer(); //se creará el objeto entero $numero = new number(); //esto producirá un error ?> Polimorfismo Los lenguajes de programación orientados a objetos admiten el polimorfismo que consiste en que las clases pueden tener diferente comportamiento. Esto se realiza implementando un método que es capaz de ejecutarse de forma diferente dependiendo del tipo y la cantidad de argumentos que reciba. En una aplicación compleja este método podría estar implementado por objetos de distinta clase y, sin embargo, no sería relevante para la aplicación dónde está realmente implementado dicho método. Lo importante es obtener el resultado esperado. Interfaces Las interfaces son similares en algunos aspectos a las clases abstractas en el sentido que no pueden instanciarse. Las interfaces han sido diseñadas para asegurar la funcionalidad dentro de una clase, definiendo un conjunto de métodos que deben tener una clase para implantar dicha interfaz. Una interfaz, a diferencia de la clase abstracta, no puede ofrecer funcionalidad, ya que sólo puede declarar métodos, no implementarlos. Para declarar una interfaz debe utilizarse la palabra reservada interface. La clase que implementará un método de la interfaz debe declararse con la palabra reservada implements nombre_interfaz, justo a continuación del nombre de la clase. Ejemplo de interfaz interface printable { public function printme(); } //Implantación de la interfaz class Integer implements printable { private $value; public function getValue(){ return (int)$this->value; } public function printme(){ echo (int)$this->value; } } Manejo de excepciones (I) Las excepciones son un concepto relativamente nuevo en PHP, que permite activar un error, no fatal, en secuencias de comando PHP. El soporte para el manejo de excepciones en PHP, nos permite producir errores y controlarlos de formas más ventajosas que los métodos que existían en la versión PHP 4. Con PHP 4 había que utilizar funciones como trigger_error() y como set_error_handler() para activar errores y procesarlos, respectivamente. Manejo de excepciones (II) En la práctica, las excepciones son instancias de clase que contienen información sobre un error que se ha producido durante la ejecución de una secuencia de comando (script). PHP 5 proporciona internamente una clase denominada Exception que posee varios métodos que obtienen información de depuración mediante la cual se puede establecer las causas de un error. Clase Exception class Exception { //Propiedades protected $message; private $string; protected $code; protected $file; protected $line; private $trace; //Métodos function __construct($message = "",$code = 0); function __toString(); public function getFile(); public function getLine(); public function getMessage(); public function getCode(); public function getTrace(); public function getTraceAsString(); } Funcionamiento del manejo de errores Las excepciones en PHP contienen dos valores principales, que son: la cadena que describe el error que se ha producido y un código entero único asociado con ese error. Cuando se produce un error PHP asigna de forma automática a la excepción la línea dentro del script y el nombre del archivo donde se ha producido dicho error. Adicionalmente, se asigna una localización de pila que representa la ruta de acceso a la ejecución que ha resultado en error. Lanzar una excepción Las excepciones son objetos de la clase predefinida exception (o de una clase derivada de esta) que se lanzan mediante la palabra reservada throw, utilizando una instrucción como la siguiente: throw new Exception($message, $coderror); La sentencia throw termina de forma súbita la ejecución del método donde se encuentre y generan un objeto de la clase Exception disponible en el contexto del objeto. Ejemplo de una excepción lanzada <?php class throwExample { public function makeError(){ throw new Exception("Esto ha generado una excepcn."); } } $inst = new throwExample(); $inst->makeError(); ?> Estructura try/catch La gestión de excepciones en PHP se realiza mediante la utilización de una estructura, nueva en PHP 5, conocida como try/catch. Su funcionamiento es relativamente simple, dentro del bloque try se colocan las instrucciones que pueden llegar a producir una excepción. Cada bloque try, debe contener, al menos, un bloque catch, con los cuales se gestionarán las excepciones. Sintaxis de la estructura try/catch Un bloque try/catch tiene la siguiente sintaxis: try { //código que se intentará ejecutar y que //puede generar una excepción } catch(classException1 $e1){ //Procesamiento de las excepciones de //classException1 } [catch(classException2 $e2){ //Procesamiento de las excepciones de //classException2 }] Ejemplo con la estructura try/catch <?php class myException extends Exception{ /* Hereda todas las propiedades y métodos de la clase Exception */ } class anotherException extends Exception{ /* De nuevo, hereda todas las propiedades y métodos de la clase Exception */ } Class throwExample{ public function makeMyException(){ throw new myException(); } public function makeAnotherException(){ throw new anotherException(); } public function makeError(){ throw new Exception(); } } … Ejemplo con la estructura try/catch … $inst = new throwExample(); try{ $inst->makeMyException(); } catch(myException $e){ echo "'myException' capturada\n"; } try{ $inst->makeAnotherException(); } catch(myException $e){ echo "'myException' capturada\n"; } catch(anotherException $e){ echo "'anotherException' capturada\n"; } try{ $inst->makeError(); } catch(myException $e){ echo "'myException' capturada\n"; } catch(anotherException $e){ echo "'anotherException' capturada\n"; } FIN