martes, 22 de enero de 2013

Herencia en PHP

La herencia es una propiedad de la programación orientada a objetos (POO), no únicamente de PHP.
La herencia nos permite utilizar una clase como base para otra, y asi podemos extender sus funcionalidades, o diseñar de una manera mejor nuestro sistema.

Por ejemplo, vamos a definir la clase persona de la siguiente manera:
class Persona {
	var $nombre;
	var $apellido;
	var $dni;
	var $calle;
 
 
	function __construct($nombre, $apellido, $dni, $calle) {
		print "Creando objecto de la clase Persona con nombre completo: " .
			   $nombre . " " . $apellido . " y DNI: " . $dni . "\n";
		$this->nombre = $nombre;
		$this->apellido = $apellido;
		$this->dni = $dni;
		$this->calle = $calle;
	}

	function mostrarDatos(){
		print "Nombre: " .  $this->nombre .  "\n";
		print "Apellido: " .  $this->apellido .  "\n";
		print "DNI: " .  $this->dni . "\n";
		print "Calle: " .  $this->calle . "\n\n";
	}
}
Como podemos ver, la clase persona tiene 4 atributos: nombre, apellido, dni y calle; ademas de la funcion mostrarDatos.

Ahora imaginemos que queremos construir un sistema en el cual tenemos compradores y vendedores.
Ambos heredaran de persona, pero cada clase tendrá sus propias propiedades:
  • Los vendedores tienen un atributo especifico que undica su número de vendedor. También pueden vender productos, cosa que no pueden los compradores.
  • A su vez, los compradores pueden comprar productos y no tienen número de vendedor, ni nada.

Estas clases quedarían definidas de la siguiente manera:

class Vendedor extends Persona {
	var $identificadorVendedor;

	function __construct($nombre, $apellido, $dni, $calle, $identificadorVendedor) {
		parent::__construct($nombre, $apellido, $dni, $calle);
		$this->identificadorVendedor = $identificadorVendedor;
		print  $nombre . " es un VENDEDOR \n";
	}

	function vender() {
		print "Vendedor " .  $this->nombre . " con numero: " . $this->identificadorVendedor . ", vende un producto \n";
	}
}

class Comprador extends Persona {
	
	function comprar() {
		print "Comprador " .  $this->nombre . " compra un producto\n";
	}
}
Ahora que tenemos nuestras clases definidas vamos a probar a crear un par de vendedores y compradores, y ver que podemos hacer con ellos.
$pedro = new Vendedor ("Pedro", "Sanchez", "40123903K", "Calle Falsa 123", "4214");
$juan = new Comprador("Juan", "Gabilondo", "10392129E", "Calle Loca n: 2");

$pedro->vender();
$juan->comprar();

La salida que obtenemos es la siguiente:
Creando objecto de la clase Persona con nombre completo: Pedro Sanchez y DNI: 40123903K
Pedro es un VENDEDOR 
Creando objecto de la clase Persona con nombre completo: Juan Gabilondo y DNI: 10392129E
Vendedor Pedro con numero: 4214, vende un producto 
Comprador Juan compra un producto

Podemos observar varias cosas:
  1. Desde el constructor de Vendedor hemos llamado al constructor del padre (clase Persona) mediante: parent::__construct($nombre, $apellido, $dni, $calle); 
  2. Que en el constructor de Vendedor, aparte de la llamada al padre hemos asignado el atributo identificadorVendedor, y hemos puesto una salida por pantalla.
  3. Cuando hemos definido la clase Comprador no hemos implementado el constructor. No ha hecho falta, pues no queriamos un comportamiento diferente al del padre (clase Persona). Y como podemos observar ha funcionado.
Podríamos probar a intentar llamar a la funcion vender desde un comprador, pero no daria ninguna salida.

Lo que si podemos hacer es llamar a los metodos del padre.
$pedro->mostrarDatos();
$juan->mostrarDatos();

Nos daría la siguiente salida:
Nombre: Pedro
Apellido: Sanchez
DNI: 40123903K
Calle: Calle Falsa 123

Nombre: Juan
Apellido: Gabilondo
DNI: 10392129E
Calle: Calle Loca n: 2

Se puede ver que de Pedro, que es vendedor, no nos apare su número de vendedor.
Si quisieramos que saliese este dato deberíamos sobreescribir la funcion mostrarDatos en la clase Vendedor. Sobreescribir consiste en escribir exactamente la misma funcion en la clase hija.

Quedaría de la siguiente manera:
class Vendedor extends Persona {
	var $identificadorVendedor;

	function __construct($nombre, $apellido, $dni, $calle, $identificadorVendedor) {
		parent::__construct($nombre, $apellido, $dni, $calle);
		$this->identificadorVendedor = $identificadorVendedor;
		print  $nombre . " es un VENDEDOR \n";
	}

	function vender() {
		print "Vendedor " .  $this->nombre . " con numero: " . $this->identificadorVendedor . ", vende un producto \n";
	}

	function mostrarDatos(){
		print "Nombre: " .  $this->nombre .  "\n";
		print "Apellido: " .  $this->apellido .  "\n";
		print "DNI: " .  $this->dni . "\n";
		print "Calle: " .  $this->calle . "\n";
		print "Numero de vendedor: " . $this->identificadorVendedor ."\n\n";
	}
}

Si ejecutamos mostrarDatos con Pedro y Juan, podemos ver que la salida cambia para Pedro (que es vendedor), pero no para Juan (que es comprador).
Nombre: Pedro
Apellido: Sanchez
DNI: 40123903K
Calle: Calle Falsa 123
Numero de vendedor: 4214

Nombre: Juan
Apellido: Gabilondo
DNI: 10392129E
Calle: Calle Loca n: 2

Podemos descargar los códigos de ejemplo en los siguientes enlaces:

No hay comentarios:

Publicar un comentario