Vous êtes sur la page 1sur 30

PHP Orientado a Objetos for Beginners

Buscando artculos de calidad para compartir con ustedes, encuentro un reciente y magnfico artculo (Object-Oriented PHP for Beginners) extrado del libro Pro PHP and jQuery, que a continuacin se los muestro, pero en nuestro idioma. He incluido los ejemplos online, para que podamos apreciarlos mejor. Y es que, para muchos programadores, la programacin orientada a objetos es un concepto aterrador, con una sintaxis muy complicada y otros temores. As pues, en este artculo aprenderemos los conceptos detrs de la Programacin Orientada a Objetos con PHP (PHP OOP), un estilo de programacin en el que las acciones relacionadas son agrupadas en clases para facilitar la creacin de un cdigo ms compacto y efectivo...

Qu es la Programacin Orientada a Objetos?


La programacin orientada a objetos es un estilo de programacin que nos permite (a los desarrolladores) agrupar tareas similares en clases. Esto ayudar a que nuestro cdigo mantenga el principio "No te repitas" (en ingls Don't Repeat Yourself o DRY, la wikipedia lo define) y as, mantenerlo fcilmente. Uno de los mayores beneficios de la programacin DRY es que, si una pieza de informacin cambia en tu programa, usualmente slo se requerir un cambio para actualizar el cdigo. Uno de las ms grandes pesadillas para los desarrolladores es mantener el cdigo cuando los datos se declaran una y otra vez, lo que significa que cualquier cambio al programa se convierte en un juego, infinitamente ms frustrante, que el Dnde est Waldo?, donde hay que atrapar el contenido y funcionalidad duplicada. OOP es intimidante para muchos de los desarrolladores porque nos introduce a una nueva sintaxis y, a simple vista, parece ser ms complejo que el sencillo cdigo estructurado o en lnea. Sin embargo, una observacin ms avispada, nos mostrar que OOP es en realidad un enfoque, en ltima instancia, sencillo y simple, de programacin. La programacin orientada a objetos es un estilo de programacin que permite a los desarrolladores agrupar tareas similares en clases.

Qu son los Objetos y Clases?


Antes de profundizar en la OOP, debemos tener una comprensin bsica de las diferencias entre Objetos y Clases. En esta seccin veremos como se construyen las clases, sus diferentes capacidades y algunos usos.

Reconociendo las diferencias entre Objetos y Clases

Fotos de Instant Jefferson y John Wardell De buenas a primeras, hay una confusin en OOP: Desarrolladores experimentados empiezan a hablar sobre objetos y clases, y estos parecen ser trminos intercambiables. Esto no es as, sin embargo, la diferencia puede ser un poco complicada de entender a primera vista. Una clase, por ejemplo, es como el plano de una casa. Define la forma de la casa en un papel, y establece las conexiones entre las diferentes partes de la casa claramente. An cuando la casa todava no existe. Un objeto, entonces, es como una casa, construida de acuerdos al plano. Los datos que se almacenan en el objeto son como la madera, cables y concreto que componen la casa: Si la casa se hubiera montado sin un plano, slo sera una pila de cosas. Sin embargo, cuando todo se junta, se convierte en una organizada y til casa. Las clases son la estructura de los datos y acciones, y usan esta informacin para construir objetos. Ms de un objeto puede ser construido de la misma clase y al mismo tiempo; estos objetos son independientes los unos de los otros. Continuando con nuestra construccin analgica, esto es similar a un condominio que puede ser construido con el mismo plano: 150 casas distintas, que lucen igual, pero que tienes diferentes familias y decoraciones por dentro.

Cmo se estructura una clase?


La sintaxis para crear una clase es muy sencilla: Declara una clase usando la palabra class, seguida del nombre de la clase y un set de llaves ({}):
<?php class MyClass { // Los mtodos y propiedades de la clase van aqu } ?>

Despus de crear la clase, una nueva clase puede ser instanciada y almacenada en una variable usando la palabra new:
<?php $obj = new MyClass; ?>

Para ver el contenido de la clase, podemos usar la funcin var_dump():


<?php var_dump($obj); ?>

Prueba este proceso, colocando el siguiente cdigo en un nuevo archivo llamado test.php (en tu localhost):
<?php class MyClass { // Los mtodos y propiedades de la clase van aqu } $obj = new MyClass; var_dump($obj); ?>

Carga la pgina en tu navegador en http://localhost/test.php y la siguiente lnea debe aparecerte:


1. object(MyClass)#1 (0) { }

De esta sencilla manera, haz completado tu primer script con OOP.

Definiendo las propiedades de una clase


Para agregar datos a la clase se usan las propiedades, o las variables de una clase especfica. stas, trabajan exactamente igual que una variable comn y corriente, excepto que ellas estn enlazadas al objeto y, por lo tanto, slo se puede acceder a ellas mediante l. Para aadir una propiedad a MyClass, aade el siguiente codigo en tu script:
<?php class MyClass { public $prop1 = "Soy la propiedad de una clase!"; } $obj = new MyClass; var_dump($obj); ?>

La palabra public determina la visibilidad de la propiedad, aprenders un poco ms sobre esto en unos momentos. Luego, la propiedad es llamada usando la sintaxis estndar de una variable, y un valor le es asignado (Aunque, las propiedades de una clase no necesitan de un valor inicial). Para leer esta propiedad e imprimirla en el navegador, vamos a hacer referencia al objeto que la contiene:
<?php echo $obj->prop1; ?>

Debido a que pueden existir mltiples instancias de una clase, si el objeto no es referenciado individualmente, el script ser incapaz de determinar cual objeto leer. El uso de la flecha (->) es un operador OOP que accede al contenido de propiedades y mtodos de un objeto dado. Modifica el script en test.php para imprimir la propiedad en vez de volcar toda la clase, modificando el cdigo como se muestra:
<?php class MyClass { public $prop1 = "Soy la propiedad de una clase!"; } $obj = new MyClass; echo $obj->prop1; // Imprime la propiedad ?>

Recarga el navegador y ahora aparecer lo siguiente:


Soy la propiedad de una clase!

Definiendo los mtodos de una clase


Los mtodos son las funciones de una clase especfica. Es decir, que las acciones individuales que un objeto ser capaz de realizar, estn definidas, dentro de una clase, como mtodos. Por ejemplo, para crear mtodos que establecen y obtienen el valor de una propiedad $prop1, aade lo siguiente a tu cdigo:
<?php class MyClass { public $prop1 = "Soy la propiedad de una clase!"; public function setProperty($newval) { $this->prop1 = $newval; } public function getProperty() { return $this->prop1 . "<br />"; } } $obj = new MyClass; echo $obj->prop1; ?>

Nota: OOP permite a los objetos referenciarse a si mismos utilizando $this. Cuando trabajamos con un mtodo, usa $this de la misma manera que usaras el nombre del objeto fuera de la clase. Para usar estos mtodos, hay que llamarlos como a cualquier funcin; pero primero, hay que referenciar al objeto que lo contiene. Imprime la propiedad de MyClass, cambia su valor e imprmelo otra vez, realizando las modificaciones que a continuacin se indican.
<?php class MyClass { public $prop1 = "Soy la propiedad de una clase!"; public function setProperty($newval) { $this->prop1 = $newval; }

public function getProperty() { return $this->prop1 . "<br />"; } } $obj = new MyClass; echo $obj->getProperty(); // Imprime el valor de la propiedad $obj->setProperty("Soy el nuevo valor de la propiedad!"); // Establece un valor nuevo echo $obj->getProperty(); // Imprime nuevamente para ver el cambio ?>

Recarga el navegador, y vers lo siguiente:


Soy la propiedad de una clase! Soy el nuevo valor de la propiedad!

El poder de la programacin orientada a objetos se hace evidente cuando se utilizan varias instancias de la misma clase.
<?php class MyClass { public $prop1 = "Soy la propiedad de una clase!"; public function setProperty($newval) { $this->prop1 = $newval; } public function getProperty() { return $this->prop1 . "<br />"; } } // Create two objects $obj = new MyClass; $obj2 = new MyClass; // Get the value of $prop1 from both objects echo $obj->getProperty(); echo $obj2->getProperty(); // Set new values for both objects $obj->setProperty("Soy el nuevo valor de la propiedad!"); $obj2->setProperty("Yo pertenezco a la segunda instancia!"); // Output both objects' $prop1 value echo $obj->getProperty(); echo $obj2->getProperty(); ?>

Cuando recargues el navegador, aparecer lo que sigue:


Soy la propiedad de una clase! Soy la propiedad de una clase! Soy el nuevo valor de la propiedad! Yo pertenezco a la segunda instancia!

Como puedes ver, OOP mantiene los objetos como entidades separadas, lo que facilita la separacin de diferentes piezas de cdigo en pequeos, pero relacionados, paquetes. De esta manera ya tenemos claro lo que es la programacin orientada a objetos, el concepto de Clases y Objetos, la distincin entre ellos, y las definiciones de propiedades y mtodos. Todo breve y claramente explicado. Ahora vamos a conocer sobre los mtodos mgicos y observar como funcionan los constructores y destructores, como podemos convertir un objeto en un string y como usar las herencias. Y todo explicado de una manera sencilla y prctica...

Los mtodos mgicos en OOP


Para facilitar el uso de objetos, PHP proporciona una serie de mtodos mgicos o mtodos especiales que son llamados cuando ciertas acciones comunes ocurren dentro de los objetos. Esto permite a los desarrolladores realizar una variedad de tareas tiles con cierta facilidad.

Usando Constructores y Destructores


Cuando un objeto es instanciado, muchas veces es conveniente establecer algunas cosas. Por ello, PHP proporciona el mtodo mgico __construct(), que se llamar automticamente cada vez que un nuevo objeto es creado. Para ilustrar el concepto de constructores, vamos a aadir un constructor a MyClass que imprimir un mensaje cuando una nueva instancia de la clase sea creada:
<?php class MyClass { public $prop1 = "Soy la propiedad de una clase!"; public function __construct() { echo 'La clase "', __CLASS__, '" fue iniciada!<br />'; } public function setProperty($newval) { $this->prop1 = $newval; }

public function getProperty() { return $this->prop1 . "<br />"; } } // Crea un nuevo objeto $obj = new MyClass; // Imprime el valor de $prop1 echo $obj->getProperty(); // Imprime un mensaje al final del archivo echo "Fin del archivo.<br />"; ?>

Toma nota: __CLASS__ retorna el nombre de la clase que fue llamada; esto es conocido como una constante mgica. Hay una amplia gama de constantes mgicas disponibles, puedes leer un poco ms de ellas en el manual de PHP. Ahora recarga el archivo en tu navegador y vers el siguiente resultado:
La clase "MyClass" fue iniciada! Soy la propiedad de una clase! Fin del archivo.

Para llamar a una funcin cuando el objeto se destruye, podemos hacer uso del mtodo mgico __destruct(). Este es muy til para la limpieza de una clase (cerrar la conexin a una base de datos, por ejemplo). Continuando con nuestro ejemplo, imprimiremos un mensaje cuando el objeto es destruido. Para ello, definimos el mtodo __destruct() en MyClass:
<?php class MyClass { public $prop1 = "Soy la propiedad de una clase!"; public function __construct() { echo 'La clase "', __CLASS__, '" fue iniciada!<br />'; } public function __destruct() { echo 'La clase "', __CLASS__, '" fue destruida!<br />'; } public function setProperty($newval) { $this->prop1 = $newval; } public function getProperty()

{ return $this->prop1 . "<br />"; } } // Crea un nuevo objeto $obj = new MyClass; // Imprime el valor de $prop1 echo $obj->getProperty(); // Imprime un mensaje al final del archivo echo "Fin del archivo.<br />"; ?>

Con el destructor definido, recarga la pgina de ejemplo y deber aparecerte el siguiente resultado:
La clase "MyClass" fue iniciada! Soy la propiedad de una clase! Fin del archivo. La clase "MyClass" fue destruida!

PHP libera todos los recursos, cuando llega al final del archivo. Para entender mejor como funciona el destructor, ahora destruye manualmente el objeto usando la funcin unset():
<?php class MyClass { public $prop1 = "Soy la propiedad de una clase!"; public function __construct() { echo 'La clase "', __CLASS__, '" fue iniciada!<br />'; } public function __destruct() { echo 'La clase "', __CLASS__, '" fue destruida!<br />'; } public function setProperty($newval) { $this->prop1 = $newval; } public function getProperty() { return $this->prop1 . "<br />"; } } // Crea un nuevo objeto

$obj = new MyClass; // Imprime el valor de $prop1 echo $obj->getProperty(); // Destruye el objeto unset($obj); // Imprime un mensaje al final del archivo echo "Fin del archivo.<br />"; ?>

Ahora recarga la pgina y vers como el resultado ha cambiado:


La clase "MyClass" fue iniciada! Soy la propiedad de una clase! La clase "MyClass" fue destruida! Fin del archivo.

Convirtiendo un Objeto a String


Para evitar que un error aparezca al intentar imprimir la instancia de MyClass como string ( cadena de texto), otro mtodo mgico es til: __toString(). Si no utilizamos __toString(), tratar de imprimir un objeto como cadena nos devolver un error fatal. Para demostrarlo, intenta imprimir el objeto con un echo, sin utilizar el mtodo mgico:
<?php class MyClass { public $prop1 = "Soy la propiedad de una clase!"; public function __construct() { echo 'La clase "', __CLASS__, '" fue iniciada!<br />'; } public function __destruct() { echo 'La clase "', __CLASS__, '" fue destruida!<br />'; } public function setProperty($newval) { $this->prop1 = $newval; } public function getProperty() { return $this->prop1 . "<br />"; } }

// Crea un nuevo objeto $obj = new MyClass; // Imprime el objeto como un string echo $obj; // Destruye el objeto unset($obj); // Imprime un mensaje al final del archivo echo "Fin del archivo.<br />"; ?>

Esto resulta en lo siguiente:


La clase "MyClass" fue iniciada! Catchable fatal error: Object of class MyClass could not be converted to string in /Applications/XAMPP/xamppfiles/htdocs/testing/test.php on line 40

Para evitar este error, vamos a aadir el mtodo __toString():


<?php class MyClass { public $prop1 = "Soy la propiedad de una clase!"; public function __construct() { echo 'La clase "', __CLASS__, '" fue iniciada!<br />'; } public function __destruct() { echo 'La clase "', __CLASS__, '" fue destruida!<br />'; } public function __toString() { echo "Usando el mtodo toString: "; return $this->getProperty(); } public function setProperty($newval) { $this->prop1 = $newval; } public function getProperty() { return $this->prop1 . "<br />"; } } // Crea un nuevo objeto

$obj = new MyClass; // Imprime el objeto como un string echo $obj; // Destruye el objeto unset($obj); // Imprime un mensaje al final del archivo echo "Fin del archivo.<br />"; ?>

En este caso, el intentar convertir el objeto en un string nos devuelve una llamada al mtodo getProperty(). Carga el script en un archivo y prubalo en el navegador. Vers que aparece lo siguiente:
La clase "MyClass" fue iniciada! Usando el mtodo toString: Soy la propiedad de una clase! La clase "MyClass" fue destruida! Fin del archivo.

Tip: Adicionalmente a los mtodos mgicos comentados en este artculo, existen ms de ellos. Para una revisin completa de los mtodos mgicos, puedes darle una mirada a esta pgina del manual de PHP.

Usando herencia de clases


Las clases pueden heredar los mtodos y propiedades de otras clases usando la palabra extends. Por ejemplo, para crear una segunda clase que extienda MyClass y aada un mtodo, podras aadir los siguiente a tu archivo de prueba:
<?php class MyClass { public $prop1 = "Soy la propiedad de una clase!"; public function __construct() { echo 'La clase "', __CLASS__, '" fue iniciada!<br />'; } public function __destruct() { echo 'La clase "', __CLASS__, '" fue destruida!<br />'; } public function __toString() { echo "Usando el mtodo toString: "; return $this->getProperty(); } public function setProperty($newval)

{ $this->prop1 = $newval; } public function getProperty() { return $this->prop1 . "<br />"; } } class MyOtherClass extends MyClass { public function newMethod() { echo "Desde un nuevo mtodo en " . __CLASS__ . ".<br />"; } } // Crea un nuevo objeto $newobj = new MyOtherClass; // Imprime el objeto como un string echo $newobj->newMethod(); // Usa el mtodo de la clase padre echo $newobj->getProperty(); ?>

Ahora, recarga el archivo en el navegador y te aparecer lo que sigue:


La clase "MyClass" fue iniciada! Desde un nuevo mtodo en "MyOtherClass". Soy la propiedad de una clase! La clase "MyClass" fue destruida!

Sobrescribiendo las propiedades y mtodos heredados


Para cambiar el comportamiento de una propiedad o mtodo en una nueva clase, simplemente podras sobrescribirlos, declarndolos otra vez en la nueva clase:
<?php class MyClass { public $prop1 = "Soy la propiedad de una clase!"; public function __construct() { echo 'La clase "', __CLASS__, '" fue iniciada!<br />'; } public function __destruct() { echo 'La clase "', __CLASS__, '" fue destruida!<br />'; }

public function __toString() { echo "Usando el mtodo toString: "; return $this->getProperty(); } public function setProperty($newval) { $this->prop1 = $newval; } public function getProperty() { return $this->prop1 . "<br />"; } } class MyOtherClass extends MyClass { public function __construct() { echo "Un nuevo constructor en " . __CLASS__ . ".<br />"; } public function newMethod() { echo "Desde un nuevo mtodo en " . __CLASS__ . ".<br />"; } } // Crea un nuevo objeto $newobj = new MyOtherClass; // Imprime el objeto como un string echo $newobj->newMethod(); // Usa el mtodo de la clase padre echo $newobj->getProperty(); ?>

Esto cambiar la salida en el navegador a:


Un nuevo constructor en MyOtherClass. Desde un nuevo mtodo en MyOtherClass. Soy la propiedad de una clase! La clase "MyClass" fue destruida!

Preservando la funcionalidad del mtodo original cuando sobrescribimos mtodos heredados


Para aadir una nueva funcionalidad a un mtodo heredado, pero queremos mantener intacto a este, vamos a usar la palabra parent con el operador de resolucin de mbito (::):

<?php class MyClass { public $prop1 = "Soy la propiedad de una clase!"; public function __construct() { echo 'La clase "', __CLASS__, '" fue iniciada!<br />'; } public function __destruct() { echo 'La clase "', __CLASS__, '" fue destruida!<br />'; } public function __toString() { echo "Usando el mtodo toString: "; return $this->getProperty(); } public function setProperty($newval) { $this->prop1 = $newval; } public function getProperty() { return $this->prop1 . "<br />"; } } class MyOtherClass extends MyClass { public function __construct() { parent::__construct(); // LLama al constructor de la clase padre echo "Un nuevo constructor en " . __CLASS__ . ".<br />"; } public function newMethod() { echo "Desde un nuevo mtodo en " . __CLASS__ . ".<br />"; } } // Crea un nuevo objeto $newobj = new MyOtherClass; // Imprime el objeto como un string echo $newobj->newMethod(); // Usa el mtodo de la clase padre echo $newobj->getProperty(); ?>

Esto muestra el resultado de ambos: Del constructor de la clase padre y del constructor de la nueva clase:
La clase "MyClass" fue iniciada! Un nuevo constructor en MyOtherClass. Desde un nuevo mtodo en MyOtherClass. Soy la propiedad de una clase! La clase "MyClass" fue destruida!

En este artculo hemos visto, rpida y claramente, cmo funcionan los mtodos mgicos en OOP y lo prctico que pueden sernos, cmo usar los constructores y destructores y un mtodo que nos ser muy til para imprimir nuestros objetos. Tambin hemos comprendido el concepto de herencias y de que maneras podemos aplicarla. Ahora vamos a conocer sobre la visibilidad de los mtodos y propiedades, cmo utilizar DocBlocks para documentar nuestros scripts y vamos a comparar la programacin orientada a objetos con la procedimental, todo con ejemplos sencillos y fciles de entender...

Asignando la visibilidad de propiedades y mtodos


Para un mayor control de nuestros objetos, mtodos y propiedades hay que definir su visibilidad. Esto controla como y desde las propiedades y mtodos pueden ser accedidas. Hay tres palabras claves sobre visibilidad: public, protected y private. Adems de su visibilidad, un mtodo o una propiedad puede declararse como esttica, lo que nos permite acceder a ellas sin necesidad de instanciar la clase. Nota: La visibilidad es una caracterstica a partir de PHP 5. Puedes obtener ms informacin sobre la compatibilidad de OOP con PHP4, leyendo esta pgina del manual de PHP.

Propiedades y mtodos pblicos


Todos los mtodos y propiedades que hemos utilizado hasta ahora, han sido pblicos. Esto significa que pueden accederse a ellos, desde cualquier lugar, tanto dentro como fuera de la clase.

Propiedades y mtodos protegidos


Cuando una propiedad o un mtodo se declara como protegido, slo se puede acceder a l dentro de la misma clase o en clases descendientes (clases que extienden a la clase que contiene el mtodo protegido). Declara al mtodo getProperty() en MyClass como protegido y trata de acceder a l desde fuera de la clase:

<?php class MyClass { public $prop1 = "Soy la propiedad de una clase!"; public function __construct() { echo 'La clase "', __CLASS__, '" fue iniciada!<br />'; } public function __destruct() { echo 'La clase "', __CLASS__, '" fue destruida!<br />'; } public function __toString() { echo "Usando el mtodo toString: "; return $this->getProperty(); } public function setProperty($newval) { $this->prop1 = $newval; } protected function getProperty() { return $this->prop1 . "<br />"; } } class MyOtherClass extends MyClass { public function __construct() { parent::__construct(); echo "Un nuevo constructor en " . __CLASS__ . ".<br />"; } public function newMethod() { echo "Desde un nuevo mtodo en " . __CLASS__ . ".<br />"; } } // Crea un nuevo objeto $newobj = new MyOtherClass; // Falla al usar el mtodo protegido

echo $newobj->getProperty(); ?>

Al intentar ejecutar este script, nos aparecer el siguiente error:


La clase "MyClass" fue iniciada! Un nuevo constructor en MyOtherClass. Fatal error: Call to protected method MyClass::getProperty() from context '' in /Applications/XAMPP/xamppfiles/htdocs/testing/test.php on line 55

Ahora, crea un nuevo mtodo en MyOtherClass para llamar al mtodo getProperty():


<?php class MyClass { public $prop1 = "Soy la propiedad de una clase!"; public function __construct() { echo 'La clase "', __CLASS__, '" fue iniciada!<br />'; } public function __destruct() { echo 'La clase "', __CLASS__, '" fue destruida!<br />'; } public function __toString() { echo "Usando el mtodo toString: "; return $this->getProperty(); } public function setProperty($newval) { $this->prop1 = $newval; } protected function getProperty() { return $this->prop1 . "<br />"; } } class MyOtherClass extends MyClass { public function __construct() {

parent::__construct(); echo "Un nuevo constructor en " . __CLASS__ . ".<br />"; } public function newMethod() { echo "Desde un nuevo mtodo en " . __CLASS__ . ".<br />"; } public function callProtected() { return $this->getProperty(); } } // Crea un nuevo objeto $newobj = new MyOtherClass; // Usa el mtodo protegido desde un mtodo pblico echo $newobj->callProtected(); ?>

Esto generar el siguiente resultado:


La clase "MyClass" fue iniciada! Un nuevo constructor en MyOtherClass. Soy la propiedad de una clase! La clase "MyClass" fue destruida!

Propiedades y mtodos privados


Una propiedad o mtodo que es declarado como privado slo es accesible desde dentro de la clase que lo define. Esto significa que incluso si una nueva clase extiende la clase que define la propiedad o mtodo privado, este no estar disponible dentro de la clase hija. Para demostrarlo, declara getProperty() como privado en MyClass, y trata de llamar a callProtected() desde MyOtherClass:
<?php class MyClass { public $prop1 = "Soy la propiedad de una clase!"; public function __construct() { echo 'La clase "', __CLASS__, '" fue iniciada!<br />'; } public function __destruct()

{ echo 'La clase "', __CLASS__, '" fue destruida!<br />'; } public function __toString() { echo "Usando el mtodo toString: "; return $this->getProperty(); } public function setProperty($newval) { $this->prop1 = $newval; } private function getProperty() { return $this->prop1 . "<br />"; } } class MyOtherClass extends MyClass { public function __construct() { parent::__construct(); echo "Un nuevo constructor en " . __CLASS__ . ".<br />"; } public function newMethod() { echo "Desde un nuevo mtodo en " . __CLASS__ . ".<br />"; } public function callProtected() { return $this->getProperty(); } } // Crea un nuevo objeto $newobj = new MyOtherClass; // Usa el mtodo protegido desde un mtodo pblico echo $newobj->callProtected(); ?>

Ahora actualiza tu navegador y aparecer el siguiente error:


La clase "MyClass" fue iniciada! Un nuevo constructor en MyOtherClass. Fatal error: Call to private method MyClass::getProperty() from context 'MyOtherClass' in /Applications/XAMPP/xamppfiles/htdocs/testing/test.php on line 49

Propiedades y mtodos estticos


Un mtodo o propiedad declarado como esttico puede ser accesible sin crear instancias de la clase; simplemente basta con proporcionar el nombre de la clase, el operador de resolucin de alcance y el nombre de la propiedad o mtodo. Una de las principales ventajas de utilizar propiedades estticas es que mantienen sus valores almacenados durante la ejecucin de todo el script. Para demostrar esto, agrega una propiedad esttica llamada $count y un mtodo esttico llamado plusOne() a MyClass. Luego, configura un bucle do while para imprimir el valor incrementado de $count siempre y cuando su valor sea menor a 10:
<?php class MyClass { public $prop1 = "Soy la propiedad de una clase!"; public static $count = 0; public function __construct() { echo 'La clase "', __CLASS__, '" fue iniciada!<br />'; } public function __destruct() { echo 'La clase "', __CLASS__, '" fue destruida!<br />'; } public function __toString() { echo "Usando el mtodo toString: "; return $this->getProperty(); } public function setProperty($newval) { $this->prop1 = $newval;

} private function getProperty() { return $this->prop1 . "<br />"; } public static function plusOne() { return "La cuenta es " . ++self::$count . ".<br />"; } } class MyOtherClass extends MyClass { public function __construct() { parent::__construct(); echo "Un nuevo constructor en " . __CLASS__ . ".<br />"; } public function newMethod() { echo "Desde un nuevo mtodo en " . __CLASS__ . ".<br />"; } public function callProtected() { return $this->getProperty(); } } do { // Llama al mtodo plusOne sin instanciar MyClass echo MyClass::plusOne(); } while ( MyClass::$count < 10 ); ?>

Nota: Cuando se acceden a las propiedades estticas, el signo de dlar($) va despus del operador de resolucin de alcance. Cuando cargues el script en el navegador, vers lo siguiente:
La La La La La cuenta cuenta cuenta cuenta cuenta es es es es es 1. 2. 3. 4. 5.

La La La La La

cuenta cuenta cuenta cuenta cuenta

es es es es es

6. 7. 8. 9. 10.

Comentando con DocBlocks


Aunque no es parte oficial de la POO, el comentar al estilo DocBlock es un mtodo de documentacin ampliamente aceptado para documentar clases. Adems de proporcionar un estndar a los desarrolladores que escriben cdigo, muchos programadas de desarrollo (SDKs) han adoptado esta metodologa, tal es el caso de Eclipse o NetBeans, y es utilizado para generar code hints o sugerencias de cdigo. Un DockBlock se define mediante el uso de un bloque de comentario que empieza con un asterisco adicional: El poder real de DocBlock viene con la posibilidad de usar tags, que comienzan con el smbolo del arroba (@) seguido inmediatamente del nombre del tag y el valor del mismo. Las etiquetas o tag en DocBlock permiten a los desarrolladores definir al autor de un archivo, la licencia de una clase, la informacin de la propiedad o mtodo y otra informacin til. Las etiquetas ms utilizadas son las siguientes:
<?php /** * Este es un DocBlock muy bsico */ ?>

@author: El autor del elemento actual (que podra ser una clase, un archivo, un mtodo o cualquier otro trozo de cdigo) se enumera con esta etiqueta. Mltiples etiquetas de autor pueden ser usadas en el mismo DocBlock si hay ms de un autor. El formato para el nombre de autor es John Doe <john.doe@email.com>. @copyright: Esto significa el ao del copyright y el nombre del titular del copyright del elemento actual. El formato es 2010 Titular del Copyright. @license: Esto enlaza a la licencia del elemento actual. El formato para la informacin de la licencia es http://www.example.com/path/to/license.txt Nombre de la licencia. @var: Esto define el tipo y descripcin de una variable o propiedad de una clase. El formato es tipo y descripcin del elemento. @param: Este tag muestra el tipo y descripcin del parmetro de una funcin o mtodo. El formato es el tipo $nombre_del_elemento y descripcin del elemento.

@return: El tipo y descripcin del valor de retorno de una funcin o mtodo es provisto por este tag. El formato es el tipo y descripcin del elemento. Una clase de ejemplo comentada con DocBlock podra tener este aspecto:
<?php /** * Una clase sencilla * * Esta es una larga descripcin de la clase, * la cual ocupar tantas lineas como sea necesario. Esta * no ser necesaria, mientras la descripcin corta sea * necesaria. * * Esta descripcin puede dividirse en varios prrafos si la * descripcin merece mucha verborrea. * * @author Jason Lengstorf <jason.lengstorf@ennuidesign.com> * @copyright 2010 Ennui Design * @license <a href="http://www.php.net/license/3_01.txt" title="http://www.php.net/license/3_01.txt">http://www.php.net/license/3_ 01.txt</a> PHP License 3.01 */ class SimpleClass { /** * Una variable pblica * * @var string almacena data para la clase */ public $foo; /** * Define $foo con un nuevo valor al instanciarse la clase * * @param string $val un valor requerido por la clase * @return void */ public function __construct($val) { $this->foo = $val; } /** * Multiplica dos nmeros enteros * * Acepta un par de enteros y devuelve el * producto de ambos. *

* @param int $bat un nmero a ser multiplicado * @param int $baz un nmero a ser multiplicado * @return int el propudcto de los dos parmetros */ public function bar($bat, $baz) { return $bat * $baz; } } ?>

Una vez que observes la clase anterior, los beneficios de DocBlock te parecern evidentes: todo est definido claramente para que el siguiente desarrollador pueda captar el cdigo y nunca tener que preguntarse lo que un fragmento de cdigo hace o lo que debe contener.

Comparando la programacin orientada a objetos y la procedimental


Realmente no hay una manera correcta o incorrecta de escribir cdigo. Dicho esto, esta seccin presenta un argumento de peso para adoptar un enfoque orientado a objetos en el desarrollo de software, especialmente en aplicaciones de gran tamao.

Razn 1: Fcil de implementar


Si bien puede se un poco desalentador al principio, la programacin orientada a objetos en realidad ofrece un enfoque ms fcil para manejar datos. Debido a que un objeto puede almacenar datos internos, no se necesita pasar variables de una funcin a otra funcin para que trabajen apropiadamente. Adems, dado que varias instancias de la misma clase pueden existir simultneamente, tratar con grandes conjuntos de datos es infinitamente ms sencillo. Por ejemplo, imagina que tienes informacin de dos personas que estn siendo procesados en un mismo archivo. Se necesitan los nombres, ocupaciones y edades.
El enfoque procedimental

Este es el enfoque procedimental de nuestro ejemplo: Cuando los ejecutes, el cdigo nos mostrar lo siguiente:
<?php function changeJob($person, $newjob) { $person['job'] = $newjob; // Cambiar el trabajo de la persona return $person; }

function happyBirthday($person) { ++$person['age']; // Aade 1 a la edad de la persona return $person; } $person1 = array( 'name' => 'Tom', 'job' => 'Button-Pusher', 'age' => 34 ); $person2 = array( 'name' => 'John', 'job' => 'Lever-Puller', 'age' => 41 ); // Imprime los valores iniciales de las personas echo "<pre>Person 1: ", print_r($person1, TRUE), "</pre>"; echo "<pre>Person 2: ", print_r($person2, TRUE), "</pre>"; // Tom obtiene un ascenso y cumple aos $person1 = changeJob($person1, 'Box-Mover'); $person1 = happyBirthday($person1); // John slo cumple aos $person2 = happyBirthday($person2); // Imprime los nuevos valores de las personas echo "<pre>Person 1: ", print_r($person1, TRUE), "</pre>"; echo "<pre>Person 2: ", print_r($person2, TRUE), "</pre>"; ?>

Cuando lo ejecutamos, el cdigo nos imprimir lo siguiente:


Person 1: Array ( [name] => Tom [job] => Button-Pusher [age] => 34 ) Person 2: Array ( [name] => John [job] => Lever-Puller [age] => 41 )

Person 1: Array ( [name] => Tom [job] => Box-Mover [age] => 35 ) Person 2: Array ( [name] => John [job] => Lever-Puller [age] => 42 )

Aunque este cdigo no sea necesariamente malo, hay que tener varias cosas en cuenta mientras se programa. El array de atributos de la persona afectada deben ser pasados y devueltos en cada llamada a la funcin, lo que deja un margen de error. Para limpiar este ejemplo, sera conveniente dejarle menos cosas al desarrollador. Slo la informacin esencial para la operacin debe necesitar ser transmitida a las funciones. Aqu es donde la POO avanza y puede ayudarte a limpiar las cosas.
El enfoque POO

Este es el enfoque POO de nuestro ejemplo:


<?php class Person { private $_name; private $_job; private $_age; public function __construct($name, $job, $age) { $this->_name = $name; $this->_job = $job; $this->_age = $age; } public function changeJob($newjob) { $this->_job = $newjob; } public function happyBirthday() { ++$this->_age; } }

// Crea dos personas nuevas $person1 = new Person("Tom", "Button-Pusher", 34); $person2 = new Person("John", "Lever Puller", 41); // Imprime su punto de inicio echo "<pre>Person 1: ", print_r($person1, TRUE), "</pre>"; echo "<pre>Person 2: ", print_r($person2, TRUE), "</pre>"; // Da a Tom un ascenso y un cumpleaos $person1->changeJob("Box-Mover"); $person1->happyBirthday(); // John slo obtiene un ao ms $person2->happyBirthday(); // Imprime los valores finales echo "<pre>Person 1: ", print_r($person1, TRUE), "</pre>"; echo "<pre>Person 2: ", print_r($person2, TRUE), "</pre>"; ?>

Esto imprimir lo siguiente en el navegador:


Person 1: Person Object ( [_name:private] => Tom [_job:private] => Button-Pusher [_age:private] => 34 ) Person 2: Person Object ( [_name:private] => John [_job:private] => Lever Puller [_age:private] => 41 ) Person 1: Person Object ( [_name:private] => Tom [_job:private] => Box-Mover [_age:private] => 35 ) Person 2: Person Object ( [_name:private] => John [_job:private] => Lever Puller [_age:private] => 42 )

Hay unos bits adicionales involucrados en el enfoque orientado a objetos, pero luego de que la clase es definida, crear y modificar personas es muy sencillo; la informacin de la persona no necesitar ser pasada o devuelta de los mtodos y slo la informacin escencial es transmitida a cada mtodo. En menor medida, esta diferencia puede no parecer mucha, pero conforme las aplicaciones crezcan en tamao, POO reducir significativamente la carga de trabajo, si se aplica correctamente. Consejo: No todo tiene que ser orientado a objetos. Una funcin rpida que se ocupa de algo pequeo en un lugar o dentro de una aplicacin no necesita tener que estar envuelta en una clase. Utiliza tu juicio para decidir que enfoque utilizar, el orientado a objetos o el procedimental.

Razn 2: Mejor organizacin


Otro beneficio de la POO es lo bien que se presta para ser empaquetado y catalogado. Cada clase en general se puede mantener en su archivo por separado, y si una convencin de nomenclatura uniforme es utilizada, acceder a las clases ser extremadamente simple. Supongamos que tenemos una aplicacin con 150 clases que se llaman de forma dinmica a travs de un archivo controlador en la raiz de nuestra aplicacin. Todas las 150 clases siguen la convencin de nomenclatura class.classname.inc.php y residen en la carpeta inc de nuestra aplicacin. El controlador puede implementar la funcin __autoload() de PHP para cargar de forma dinmica slo las clases que van a necesitar ser llamadas, en lugar de tener que incluir los 150 archivos en el controlador:
<?php function __autoload($class_name) { include_once 'inc/class.' . $class_name . '.inc.php'; } ?>

Tener cada clase en un archivo separado, tambin permite que el cdigo sea ms porttil y ms fcil de reutilizar en nuevas aplicaciones, sin necesidad de copiar y pegar.

Razn 3: Un mantenimiento ms fcil


Debido a la naturaleza ms compacta de la programacin orientada a objetos, cuando se aplica correctamente; los cambios en el cdigo son generalmente mucho ms fcil de detectar y cambiar que en un cdigo espagueti de implementacin procedimental.

Si un array de informacin obtiene un nuevo atributo, el enfoque procedimental podr requerir (en el peor de los casos) que el nuevo atributo se aada en cada funcin que utilice el array. Una aplicacin POO podra actualizarse con la misma facilidad con la que se agrega una nueva propiedad y, a continuacin, aade los mtodos que tienen que ver con dicha propiedad. Muchos de los beneficios cubiertos en esta serie de artculos son el producto de la POO en combinacin con las prcticas de desarrollo DRY. Definitivamente, es posible crear un cdigo procedimental que no nos de pesadillas; pero, es igualmente posible crear un cdigo orientado a objetos terrible. Por eso, hemos intentado demostrar como combinar los buenos hbitos de programacin relacionados con la programacin orientada a objetos para generar un cdigo limpio, que sea fcil de leer y mantener.

Conclusiones
En este momento, debes sentirte cmodo con el estilo de la programacin orientada a objetos. Aprender POO es una muy buena forma de llevar tu programacin al siguiente nivel. Cuando se implementa correctamente, la programacin orientada a objetos te ayudar a leer y mantener el cdigo fcilmente; y te salvar (y a los desarrolladores que trabajan contigo) de horas extra de trabajo. Estas metido en algo que no ha sido tratado en esta serie de artculos? Ya utilizas la POO y tienes algunos ejemplos para principiantes? Comprtelos en los comentarios!

Vous aimerez peut-être aussi