Sobrecarga de constructores en PHP

  • Por
  • PHP
Cómo podemos fabricar por nosotros mismos un sistema de sobrecarga de métodos, no soportada de manera nativa en PHP, en el caso específico de constructores, tan importante para la reutilización del código.

La Programación Orientada a Objetos (POO) en PHP tiene una carencia que considero fundamental y quien venga de otros lenguajes la echará seriamente en falta. Se trata de la sobrecarga de métodos, que es uno de los pilares fundamentales que hace de la POO una gran forma de crear software más versátil y que reutilice más código.

En este artículo estudiaremos una alternativa muy sencilla, pero totalmente funcional para poder simular la sobrecarga de métodos, de modo que aprovechemos sus posibilidades tal como si fuera algo nativamente soportado por PHP. En concreto, encararemos el problema con los métodos constructores, de modo que podamos construir objetos con distintos juegos de parámetros.

¿Por qué no hay sobrecarga de métodos en PHP?

Al notar la falta de sobrecarga de métodos en la Programación Orientada a Objetos implementada en PHP, uno se puede quedar pensando ¿por qué no existe en PHP? ¿no se trata de una POO devaluada debido a la carencia de sobrecarga? ¿cómo puedo hacer clases que tengan constructores que acepten varios juegos de parámetros?

Después de analizar la situación, podemos observar que en PHP sufrimos la carencia de sobrecarga debido a que es un lenguaje poco estricto. En el caso de las funciones, PHP tiene la particularidad de permitir invocarlas enviando un juego de parámetros diferente al que fue declarada. Sin invocamos una función sin enviarle todos los parámetros, PHP dará mensajes de advertencia, pero el código se ejecuta. Si al invocar una función enviamos más parámetros de los que tocaba, ni siquiera nos da un mensaje de advertencia.

Es por ello que no pueden coexistir funciones con el mismo nombre y distintos juegos de parámetros, porque PHP siempre va a utilizar la función que se declare (una única vez), enviando los parámetros de que disponga en el momento se su invocación.

¿Cómo simular la sobrecarga de métodos constructores?

La salida que nos queda para aprovechar las posibilidades de la sobrecarga de métodos es programarla "a mano". Se trata de un proceso sencillo de incorporar, aunque no cabe duda de que es más bonito cuando está admitido por el lenguaje de manera nativa.

Nota: Este ejemplo lo hemos aplicado a constructores, pero podría servirnos crear un esquema similar con el que sobrecargar cualquier método que necesitemos. Puedes ver cómo son los constructores de PHP en un artículo anterior.

El truco está en tener un método "genérico" que no recibe parámetros y un método específico para cada número de parámetros que pensemos aceptar. El método "genérico" lo declaramos sin indicar ningún parámetro y dentro de su código utilizar la función de PHP func_get_args(), que nos permite de manera genérica extraer todos los parámetros que pueda estar recibiendo la función. Una vez sabemos el número de parámetros que nos han enviado en tiempo de ejecución, podemos invocar a la función específica que tiene el código a ejecutar cuando se recibe ese número concreto de parámetros.

Viendo el código del siguiente ejemplo y leyendo sus comentarios podremos entender mejor esta técnica.

class jugador
{
	private $nombre;
	private $equipo;
	function __construct()
	{
		//obtengo un array con los parámetros enviados a la función
		$params = func_get_args();
		//saco el número de parámetros que estoy recibiendo
		$num_params = func_num_args();
		//cada constructor de un número dado de parámtros tendrá un nombre de
		función
		//atendiendo al siguiente modelo __construct1() __construct2()...
		$funcion_constructor ='__construct'.$num_params;
		//compruebo si hay un constructor con ese número de parámetros
		if (method_exists($this,$funcion_constructor)) {
			//si existía esa función, la invoco, reenviando los parámetros que recibí en el constructor original
			call_user_func_array(array($this,$funcion_constructor),$params);
		}
	}
	//ahora declaro una serie de métodos constructores que aceptan diversos números de
	parámetros
	function __construct0()
	{
		$this­>__construct1("Anónimo");
	}
	function __construct1($nombre)
	{
		$this­>__construct2($nombre, "Sin equipo");
	}
		function __construct2($nombre, $equipo)
	{
		$this­>nombre = $nombre;
		$this­>equipo = $equipo;
	}
}

Podrían existir otros mecanismos para obtener sobrecarga de constructores en PHP, pero éste que hemos visto creo que es el más limpio y el que mejor respeta la filosofía de la Programación Orientada a Objetos.

Autor

Miguel Angel Alvarez

Miguel es fundador de DesarrolloWeb.com y la plataforma de formación online EscuelaIT. Comenzó en el mundo del desarrollo web en el año 1997, transformando su hobby en su trabajo.

Compartir

Comentarios

Pablo Daniel Almada

12/11/2013
Sobrecarga de constructores
Interesante.

nidark

19/11/2013
Constructores sobrecargados
Muy buen articulo, pero me parece un poco exagerada la manera de hacer un constructor sobrecargado. Creo que la utilización de este código es muy compleja para el uso de los constructores. Ademas imagínense un objeto con 10 o 15 propiedades, van a hacer 15 métodos???? Me parece que este código es mucho mas sencillo y cumple la misma función:

class Persona{

private $nombre;
private $apellido;
private $edad;

function __construct ($nombre=null, $apellido=null, $edad=null) {

$this->$nombre = $nombre;
$this->$apellido= $apellido;
$this->$edad= $edad;
}
}

De esta manera inicializamos las propiedades en null dentro del constructor, significa que si no son enviadas en la llamada del método su valor será null. En mi humilde opinión esta es una solución mucho más limpia y cumple el mismo objetivo.

nidark

19/11/2013
Arreglo de la funcion
Anteriormente me equivoque en la función ya que agregue el signo $ en la llamada de las propiedades. La función seria de esta manera:

function __construct ($nombre=null, $apellido=null, $edad=null) {

$this->nombre = $nombre;
$this->apellido= $apellido;
$this->edad= $edad;
}

daniel

19/11/2013
Sobrecarga de constructores en PHP
de la forma en que dice nidark es como lo aprendi y me funciona bien.

Javi

19/11/2013
Interesante
Lo interesante de la primera propuesta (creando constructores numericamente) es poder <br />
diferenciar con facilidad la funcionalidad de cada constructor. En el caso del comentario <br />
anterior al mio (poner los valores a NULL). No es mala idea, pero si vas a hacer algo más que <br />
setear propiedades (llamar a métodos, instanciar objetos, etc) vas a tener que gestionar <br />
los NULLS para reconocer cada constructor. Puedes tener un constructor con 3 parametros, otro con 4 y otro con 9. Es más limpio (legible) separar los constructores que meter IFs o un Switch dentro del Constructor para gestionar cada ocasión.<br />
<br />
Enfin, para mi es mucho más limpio con constructores separados ( aunque sea numérico )<br />
Un saludo.

salva-navas

25/11/2013
Valores por defecto no es totalmente funcional
El uso de los valores por defecto que propone nidark no es funcional.

Fíjate en esto: ¿Cómo harías para crear una persona sin indicarle $apellidos, pero indicando $nombre y $edad?

Los valores por defecto son muy útiles, pero existe un problema. Es que si queremos asignarle valores al último parámetro, debemos necesariamente asignarle valores a todos los anteriores. Dicho de otro modo, a la vista de tu ejemplo, si quieres indicarle un valor a $edad únicamente, estás obligado a invocar la función indicando null como valores a los anteriores parámetros. Es un poco chapuza si lo comparas con las posibilidades de la sobrecarga de Java (por ejemplo), algo que se ha tratado de emular en este artículo.

Los valores por defecto de los parámetros están bien. En muchos casos son suficientes, pero no siempre cubren tus necesidades. La gestión de constructores con sobrecarga en varias funciones es muchísimo más versátil, aunque no siempre sería necesaria.

Angel

12/2/2014
Me ha gustado su solución
Miguel Ángel, me ha gustado su solución para la sobrecarga de constructores.

Samuel

09/7/2014
Lo bueno de la programación
Lo bueno de la programación es que no hay soluciones buenas y malas, si no que en cada ocasión aplicas la solución que mejor se adapta a tu problema, por lo tanto podemos decir que los dos son muy buenos.

Gracias y un saludo.