Programatik

October 29, 2007

Ejemplo de uso de eval() y objetos en PHP

Filed under: OOP, php — Rafa @ 7:30 pm

Supongamos una clase que gestiona productos con tres características fundamentales: ID, Nombre y Color.

Podemos escribir esta clase de la siguiente forma:

Class Product {
	private $id;
	private $name;
	private $colour;
 
	public function Product($id, $name, $colour) {
		$this->id = $id;
		$this->name = $name;
		$this->colour = $colour;
	}
}

Como se puede ver, el constructor recibe los detalles del producto y carga las propiedades con sus valores correspondientes.

Supongamos ahora que queremos obtener el valor de una propiedad dada del producto cargado. Con tres propiedades es sencillo, pues podríamos hacer métodos del tipo getName(), getID(), etcétera. Sin embargo, para un gran número de propiedades puede ser útil disponer de un método getProperty($name) por el cual obtendremos el valor de la propiedad indicada por el argumento $name.

Para estos casos es muy útil disponer del uso de la función eval(). De esta forma, la clase anterior se extenderá a la forma siguiente:

Class Product {
	private $id;
	private $name;
	private $colour;
 
	public function Product($id, $name, $colour) {
		$this->id = $id;
		$this->name = $name;
		$this->colour = $colour;
	}
 
	public function getProperty($name) {
		return eval("\$this->$name;");
	}
}

Nótese cómo en el cuerpo de eval colocamos una barra invertida para escapar el símbolo del dólar ($) en $this con el fin de que $this no se evalúe antes de tiempo, sino que forme parte del conjunto de la cadena a evaluar.

Un ejemplo de uso sería el siguiente:

$p =& new Product(1, "sacacorchos", "plateado");
echo $p->getProperty('Colour');

que daría como resultado “plateado”.

Enlaces

  • http://es.php.net/manual/es/function.eval.php
  • August 23, 2007

    Uso de clases abstractas

    Filed under: OOP, php — Rafa @ 12:24 pm

    Supongamos la siguiente situación:

    Tenemos que implementar un objeto que representa una figura. Sus propiedades serán base y altura. El único método será area, que calculará el área de la figura.

    Obviamente, el área se calculará de una forma u otra dependiendo de qué figura se trate.

    Una primera aproximación podría llevarnos a esto:

    Class Shape {
    	private $base;
    	private $height;
     
    	public function Shape($base, $height) {
    		$this->base = $base;
    		$this->height = $height;
    	}
     
    	public function area($type) {
    		switch ($type) {
    			case 'rectangle':
    				return $this->base * $this->height;
    				break;
     
    			case 'triangle':
    				return ($this->base * $this->height) / 2;
    				break;
    		}
    	}
     
    //
    }

    Y así deberíamos ir colocando todas las posibles figuras distintas en los casos del switch.

    Sin embargo, esto nos obliga a estar editando esta clase cada vez que queramos incluir una figura nueva a la que calcular su área.

    Una solución más elegante la proporcionan las clases abstractas. Una clase abstracta permite definir un objeto que no será instanciado, pero del que podremos heredar para crear objetos nuevos.

    En el ejemplo de la figura, el código quedaría así:

    Abstract Class Shape {
    	protected $base;
    	protected $height;
     
    	abstract public function area();
    }

    Observamos que el método area presenta solo su signatura. Su implementación debe realizarse en las clases que hereden de Shape. De este modo, podemos crear un objeto por cada figura distinta que necesitemos para trabajar.

    Por ejemplo:

    Class Rectangle extends Shape {
    	public function Rentangle($base, $height) {
    		$this->base = $base;
    		$this->height = $height;
    	}
    	public function area() {
    		return $this->base * $this->height;
    	}
    }
     
    Class Triangle extends Shape {
    	public function Triangle($base, $height) {
    		$this->base = $base;
    		$this->height = $height;
    	}
    	public function area() {
    		return ($this->base * $this->height) / 2;
    	}
    }

    o cualquier otra figura que queramos.

    Este ejemplo es muy obvio y puede encontrarse en la documentación de PHP, en uno de sus comentarios. Un ejemplo de uso menos trivial sería el siguiente:

    Imaginemos que tenemos una serie de tablas distintas en una base de datos pero que tienen la misma estructura, formada por un identificador, ID, y un campo Name.

    Podríamos crear varios objetos, uno por cada una de esas tablas, para manejar la selección y edición de datos de las mismas. Como es natural, esto se hace muy pesado porque estamos repitiendo código sin motivo. Es mejor utilizar una clase abstracta:

    Abstract Class NamedList {
     
    	protected $id;
    	protected $name;
     
    	public $data = array();
     
    	public function setID($id) {
    		$this->id = $id;
    	}
    	public function setName($name) {
    		$this->name = $name;
    	}
    	public function getID() {
    		return $this->id;
    	}
    	public function getName() {
    		return $this->name;
    	}
    	public function getData() {
    		return $this->data;
    	}
     
    //
    }

    A partir de ella podemos crear objetos que se encarguen solo del acceso a los datos:

    Class TableManagement extends NamedList {
    	public function add() {
    	}
    	public function update($id) {
    	}
    	public function delete($id) {
    	}
     
    	// ...
    }

    Enlaces

  • http://www.php.net/manual/en/language.oop5.abstract.php#75990
  • Powered by WordPress