lunes, 17 de junio de 2013

Poo en PHP


Programación Orientada a Objetos en PHP


Clase constructor

Los constructores son funciones, o métodos, que se encargan de realizar las tareas de inicialización de los objetos al ser instanciados. Es decir, cuando se crean los objetos a partir de las clases, se llama a un constructor que se encarga de inicializar los atributos del objeto y realizar cualquier otra tarea de inicialización que sea necesaria.
No es obligatorio disponer de un constructor, pero resultan muy útiles y su uso es muy habitual. En el ejemplo de la caja, que comentábamos en el anterior artículo de programación orientada a objetos en PHP, lo normal sería inicializar las variables como color o las relacionadas con las dimensiones y, además, indicar que el contenido de la caja está vacío. Si no hay un constructor no se inicializan ninguno de los atributos de los objetos.
El constructor se define dentro de la propia clase, como si fuera otro método. El único detalle es que el constructor debe tener el mismo nombre que la clase. Atentos a PHP, que diferencia entre mayúsculas y minúsculas.
Para la clase Caja definida anteriormente, se podría declarar este constructor:
function Caja($alto=1,$ancho=1,$largo=1,$color="negro"){
    $this->alto=$alto;
    $this->ancho=$ancho;
    $this->largo=$largo;
    $this->color=$color;
    $this->contenido="";
}
En este constructor recibimos por parámetro todos los atributos que hay que definir en una caja.
Es muy útil definir unos valores por defecto en los parámetros que recibe el constructor, igualando el parámetro a un valor dentro de la declaración de parámetros de la función constructora, pues así, aunque se llame al constructor sin proporcionar parámetros, se inicializará con los valores por defecto que se hayan definido.
Es importante señalar que en los constructores no se tienen por qué recibir todos los valores para inicializar el objeto. Hay algunos valores que pueden inicializarse a vacío o a cualquier otro valor fijo, como en este caso el contenido de la caja, que inicialmente hemos supuesto que estará vacía.


void __construct ([ mixed $args [, $... ]] )
Por motivos de compatibilidad, si PHP 5 no puede encontrar una función __construct() para una determinada clase y la clase no heredó uno de una clase padre, buscará el viejo estilo de la función constructora, mediante el nombre de la clase. Efectivamente, esto significa que en el único caso en el que se tendría compatibilidad es si la clase tiene un método llamado __construct() que fuese utilizado para diferentes propósitos.
A diferencia con otros métodos, PHP no generará un mensaje de error a nivel de E_STRICT cuando __construct() es sobrescrito con diferentes parámetros que los métodos padre __construct() tienen.
A partir de PHP 5.3.3, los métodos con el mismo nombre que el último elemento de una clase en un nombre de espacios no serán más tratados como un constructor. Este cambio no afecta a clases sin espacio de nombres.
PHP 5 permite a los desarrolladores declarar métodos constructores para las clases. Aquellas que tengan un método constructor lo invocarán en cada nuevo objeto creado, lo que lo hace idóneo para cualquier inicialización que el objeto pueda necesitar antes de ser usado.
Nota: Constructores parent no son llamados implícitamente si la clase child define un constructor. Para ejecutar un constructor parent, se requiere invocar a parent::__construct() desde el constructor child. Si el child no define un constructor, entonces se puede heredar de la clase padre como un método de clase normal (si no fue declarada como privada).

Herencia

Qué es la Herencia en PHP y como implementarla
Como su nombre indica el concepto de herencia se aplica cuando creamos una clase, que va a heredar los métodos y atributos de una ya definida, entonces la clase que hemos creado es una subclase. 
Para que una clase sea subclase de otra ya creada deberemos usar la palabra reservada extendí en el siguiente código podremos ver como creamos una clase llamada SubClaseA que heredará los métodos y atributos de una clase definida con anterioridad llamada ClaseA.
Subclase de la clase A
class SubClaseA extendí ClaseA {
   var $atributo2;
   function operacion2()
                        {
                         }
            }
Tenemos la clase ClaseA que es definida de la siguiente forma:
            Class ClaseA {
            var $atributo1;
            function operacion1()
                        {
                        }
             }
Si creamos un objeto de la clase SubClaseA este heredará todos los métodos de la clase ClaseA, por lo tanto el siguiente código es válido:
$x = new SubClaseA();
            $x->operacion1();
            $x->atributo1 = 100;
            $x->operacion2();
            $x->atributo2 = 200;
Como podemos observar aunque declaremos un objeto de la clase SubClaseA, al ser una clase extendida de ClaseA podemos hacer uso de todos los métodos y atributos definidos en ClaseA como si estuvieran contenidos en SubClaseA.
Debemos tener en cuenta que la herencia solo trabaja en una dirección, la subclase o clase hija hereda las características de su clase padre o superclase, pero la clase padre no posee las características de la hija. Para el caso anterior ClaseA no tendría atributo2 ni metodo2();



Encapsulamiento

 

Este lenguaje de programación no es muy estricto, en POO es muy bueno tener en cuenta la ocultación de información (encapsulamiento). Muchos dicen que PHP rompe el encapsulamiento debido a que nos permite acceder a cualquier atributo de una clase directamente, pero en si hay una forma de hacer que no se pueda, para generar el encapsulamiento. Para ello tenemos el concepto de visibilidad en pH.

El concepto de visibilidad nos dice que hay tres palabras claves/reservadas: public, protected y private que anteponiéndolas a cualquier método o atributo/propiedad se podrán modificar o implementar su visibilidad, haciendo posible el encapsulamiento.

Public: Se podrá acceder a ella de cualquier forma, directamente o por métodos. Ejemplo:

class Persona{
    public $nombre;
    public $apellido;
    public $edad; // Es public por lo que se accede desde cualquier parte
public function __construct($nom, $ape, $e){
        $this->nombre = $nom;
 $this->apellido= $ape;
 $this->edad = $e;
    }
    public function imprimir(){
        return $this->edad;
}
}
$persona = new Persona('Pepito','Perez',24);
 echo $persona->edad;
 echo $persona->imprimir();

Como vemos es la misma clase persona, creamos el objeto y hacemos hecho a la edad directamente, lo que nos imprimirá un 24, después por medio del método imprimir() también nos pondrá en pantalla el mismo dato, la edad.

Protected: Si cambiamos el public por el protected, y dejamos lo mismo nos saldrá un fatal error, ya que con protected no nos dejara acceder a la propiedad a menos que sea por métodos de la misma clase, herencia o con el parent.
           
class Persona{
    public $nombre;
    public $apellido;
    protected $edad;
    public function __construct($nom, $ape, $e){
        $this->nombre = $nom;
 $this->apellido= $ape;
$this->edad = $e;
    }
    public function imprimir(){
        return $this->edad;
    }
}
$persona = new Persona('Pepito','Perez',24);
echo $persona->edad;
echo $persona->imprimir();

Si comentamos la línea donde imprimimos directamente la propiedad, nos imprimirá el resultado del método imprimir().

           
//echo $persona->edad;
echo $persona->imprimir();

Private: Al poner la propiedad edad en private solo nos dejara acceder desde la misma clase, entonces si hacemos el ejercicio anterior
           
class Persona{
    public $nombre;
    public $apellido;
    private $edad;
public function __construct($nom, $ape, $e){
        $this->nombre = $nom;
 $this->apellido= $ape;
 $this->edad = $e;
    }
    public function imprimir(){
        return $this->edad;
}
}
class trabajo extendí Persona{
    public $trabajos;
    public $pruebas;
    public function trabajar($Job){
$this->taboos = $job;
    }
    public function imprimir(){
retorno 'Mi nombre es '.$this->nombre.' '.$this->apellido.' y tengo '.
 $this->edad.' Años y trabajo en '.$this->trabajos;
    }
 }
$persona = new Persona('Pepito','Perez',24);
echo $persona->imprimir();

Si corremos pH con el siguiente código, no nos dejara acceder a la propiedad edad de la clase Persona desde trabajo porque es privada, si fuera protected si nos dejaría pero solo por métodos o parent.

Polimorfismo

Qué es el polimorfismo y como implementarlo
Cualquier lenguaje de programación orientado a objetos debe soportar el polimorfismo, esto significa que clases diferentes tendrán un comportamiento distinto para la misma operación. Esto lo veremos más claro con el siguiente ejemplo.
Supongamos que tenemos dos clases distintas coche y ciclomotor. Ambas tienen sus propios métodos de movimiento, éstos tienen diferentes comportamientos, pero su nombre es el mismo.
class coche {
                        function avanza() {
                        }
                        function para() {
                        }
                        function girar derecha() {
                        }
             }
Clases ciclomotor {
                        función avanza() {
                        }
                        function para() {
                        }
                        function girar_derecha() {
                        }
             }
Como podemos observar, ambas clases tienen los mismos métodos, supongamos ahora que tenemos otra clase que controla el movimiento de todos los vehículos, es aquí donde entra en juego el polimorfismo, que dependiendo del objeto que tratemos actuará de una forma u otra el método al que llamamos.
clases movimiento {
                        function mover_adelante($obj) {
                        $obj->avanza();
                        }
            }
Supongamos que queremos mover cualquier vehículo hacia adelante entonces haríamos:
$obj_coche = new coche();
            $obj_ciclomotor = new ciclomotor(); $obj_movimiento = new movimiento();
            //con esta sentencia el coche avanzaría hacia adelante.
            $obj_movimiento-> mover_adelante($obj_coche);
            //con esta sentencia el ciclomotor avanzaría hacia adelante.
            $obj_movimiento-> mover_adelante($obj_ciclomotor);
Como podemos ver el mismo método del objeto movimiento actúa de dos formas diferentes dependiendo del objeto que le pasamos como parámetro.



No hay comentarios:

Publicar un comentario