Diferencia entre revisiones de «Plantilla:PHP/Sobrecarga»
De WikiEducator
(22 revisiones intermedias por el mismo usuario no mostrado) | |||
Línea 1: | Línea 1: | ||
− | + | ||
===Sobrecarga=== | ===Sobrecarga=== | ||
Un concepto muy importante y básico en la programación orientada a objetos. | Un concepto muy importante y básico en la programación orientada a objetos. | ||
− | |||
La sobrecarga es una concreción del principio de '''polimorfismo''' | La sobrecarga es una concreción del principio de '''polimorfismo''' | ||
{{MRM_Definicion|Title=polimorfismo| | {{MRM_Definicion|Title=polimorfismo| | ||
− | *Podemos tener varios métodos con el mimos nombre, pero diferente número de parámetros o con parámetros de | + | *Podemos tener varios métodos con el mimos nombre, pero diferente número de parámetros o con parámetros de diferente tipo |
*El tiempo de ejecución se ejecutará uno u otro en función de los parámetros reales que pasemos en la invocación del método}} | *El tiempo de ejecución se ejecutará uno u otro en función de los parámetros reales que pasemos en la invocación del método}} | ||
*Sin embargo este aspecto en php no es del todo intuitivo. No existe la sobrecarga como la entendemos en otros lenguajes. | *Sin embargo este aspecto en php no es del todo intuitivo. No existe la sobrecarga como la entendemos en otros lenguajes. | ||
Línea 15: | Línea 14: | ||
{{MRM_Ejemplo| | {{MRM_Ejemplo| | ||
<source lang=php> | <source lang=php> | ||
− | function verTipoParametros($a,$b,$c){ | + | function verTipoParametros($a=null,$b=null,$c=null){ |
echo "Primer parámetro "; | echo "Primer parámetro "; | ||
var_dump($a); | var_dump($a); | ||
Línea 24: | Línea 23: | ||
} | } | ||
</source> | </source> | ||
− | + | </nowiki> | |
+ | }} | ||
+ | <br /> | ||
*Ahora la invocamos de diferente manera y vemos el resultado: | *Ahora la invocamos de diferente manera y vemos el resultado: | ||
{{MRM_Ejemplo|Title=Invocar sin parámetros reales| | {{MRM_Ejemplo|Title=Invocar sin parámetros reales| | ||
Línea 67: | Línea 68: | ||
}} | }} | ||
− | {{MRM_Ejemplo|Title=Invocar con 3 | + | {{MRM_Ejemplo|Title=Invocar con 3 parámetros reales| |
<source lang=php> | <source lang=php> | ||
... | ... | ||
− | echo "Invocando a <strong>verTipoParametros ('pedro',5,9)</strong><hr />"; | + | echo "Invocando a <strong> |
+ | verTipoParametros ('pedro',5,9) | ||
+ | </strong><hr />"; | ||
+ | |||
verTipoParametros ('pedro',5,9); | verTipoParametros ('pedro',5,9); | ||
... | ... | ||
Línea 83: | Línea 87: | ||
<source lang=php> | <source lang=php> | ||
... | ... | ||
− | echo "Invocando a <strong>verTipoParametros ([1,4,'maría'],true,'sonia')</strong><hr />"; | + | echo "Invocando a <strong> |
+ | verTipoParametros ([1,4,'maría'],true,'sonia') | ||
+ | </strong><hr />"; | ||
verTipoParametros ([1,4,'maría'],true,'sonia'); | verTipoParametros ([1,4,'maría'],true,'sonia'); | ||
... | ... | ||
</source> | </source> | ||
− | *Ahora | + | *Ahora igualmente pasamos tres parámetros, pero uno de ellos es un array |
*Podemos ver el resultado | *Podemos ver el resultado | ||
[[Imagen:funcionParametroRealArray.png]] | [[Imagen:funcionParametroRealArray.png]] | ||
Línea 93: | Línea 99: | ||
− | ===Sobrecargando el constructor=== | + | ====Sobrecargando el constructor==== |
*Usando esta forma de trabajar vamos a sobre cargar el constructor de una clase | *Usando esta forma de trabajar vamos a sobre cargar el constructor de una clase | ||
*Tomamos una clase de tipo '''''Racional'''''. Un número Racional es un objeto que tendrá numerador y denominador | *Tomamos una clase de tipo '''''Racional'''''. Un número Racional es un objeto que tendrá numerador y denominador | ||
[[Imagen:claseRacional.png]] | [[Imagen:claseRacional.png]] | ||
− | *Ahora a la hora de construir el objeto planteamos la posibilidad de | + | *Ahora a la hora de construir el objeto planteamos la posibilidad de poder instanciar de la siguiente manera: |
<source lang=php> | <source lang=php> | ||
$r1 = new Racional ("8/5");/* 8/5 */ | $r1 = new Racional ("8/5");/* 8/5 */ | ||
Línea 111: | Línea 117: | ||
<source lang=php> | <source lang=php> | ||
− | public function __construct($num, $den) { | + | public function __construct($num=1, $den=1) { |
.... | .... | ||
} | } | ||
+ | |||
</source> | </source> | ||
− | *Especificamos el código | + | *Especificamos el código de cómo se podría hacer |
− | + | ||
<source lang=php> | <source lang=php> | ||
class Racional { | class Racional { | ||
Línea 123: | Línea 129: | ||
private $den; | private $den; | ||
− | public function __construct($num, $den) { | + | public function __construct($num=1, $den=1) { |
//opciones new Racional () =>1/1 | //opciones new Racional () =>1/1 | ||
//opciones new Racional (5) =>5/1 | //opciones new Racional (5) =>5/1 | ||
Línea 129: | Línea 135: | ||
////opciones new Racional (5,2) =>5/2 | ////opciones new Racional (5,2) =>5/2 | ||
//Otra sitiación no se instancia | //Otra sitiación no se instancia | ||
− | if ( | + | if (is_string($num){ |
− | + | $numero = explode("/",$num) | |
− | + | $num = $numero[0]; | |
− | + | $den= $numero[1] | |
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
} | } | ||
+ | $this->num = $num; | ||
+ | $this->den = $den; | ||
+ | } | ||
Línea 185: | Línea 181: | ||
} | } | ||
} | } | ||
+ | </source> | ||
+ | ;Esta sería un posibilidad, pero debemos de intentar crear un código más compacto y realizar una estratelgia más compacta. El ejemplo anterior lo podríamos compactar de la siguiente manera. | ||
+ | En ella vamos a inicializar los parámetros con un valor que quiero que tengan si no se aporta valor <span class="r">1</span> | ||
+ | Posteriormente en el código establezco la situación en el caso de que el primer parámetro sea string y asigno los valores a numerador y denominador. | ||
+ | Hecho esto, ya hemos considerado todas las opciones, ahora ya solo queda inicializar los atributos con estos valores. | ||
+ | |||
+ | <source lang=php> | ||
+ | public function __construct($num=1,$den=1){ | ||
+ | if (is_string($num)){ | ||
+ | $numero= explode("/",$num); | ||
+ | $num= $numero[0]; | ||
+ | $den= $numero[1]; | ||
+ | } | ||
+ | $this->num= $num; | ||
+ | $this->den= $den; | ||
+ | } | ||
</source> | </source> | ||
*Probamos este constructor con el siguiente código | *Probamos este constructor con el siguiente código | ||
Línea 202: | Línea 214: | ||
Valor del racional $b <nowiki>=</nowiki> 5/1 | Valor del racional $b <nowiki>=</nowiki> 5/1 | ||
Valor del racional $c <nowiki>=</nowiki> 5/6 | Valor del racional $c <nowiki>=</nowiki> 5/6 | ||
− | Valor del racional $d <nowiki>=</nowiki> 6/6 | + | Valor del racional $d <nowiki>=</nowiki> 6/6 |
− | }} | + | ====Sobrecarga con __call(...)==== |
+ | *Otra forma de poder hacer lo mismo es usando el método mágico __call($funcion, $parametros). | ||
+ | {{Tip|El método mágico __call(..) es ejecutado cuando invocamos a un método que no existe en la clase}} | ||
− | * | + | *Ahora queremos usar un método llamado '''''asigna''''' que nos permita cambiar el valor de un racional. La forma de aportar el nuevo valor, queremos que sea la misma que la forma de construir el objeto |
− | < | + | <source lang=php> |
+ | $r1 = new Racional (); //construye el objeto 1/1 | ||
+ | |||
+ | $r1->asigna("6/4"); //Ahora el objeto vale 6/4 | ||
+ | $r1->asigna(); //Ahora el objeto vale 1/1 | ||
+ | $r1->asigna(8);//Ahora el objeto vale 8/1 | ||
+ | $r1->asigna(124, 6);//Ahora el objeto vale 124/6 | ||
+ | </source> | ||
+ | *La forma de proceder será usando los métodos privados creados anteriormente | ||
+ | *El siguiente código implementa la solución | ||
<source lang=php> | <source lang=php> | ||
− | + | public function __call($metodo, $argumentos) { | |
− | + | if ($metodo == "asigna"){ | |
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | if ($metodo = "asigna"){ | + | |
switch (count($argumentos)){ | switch (count($argumentos)){ | ||
case 0: | case 0: | ||
Línea 257: | Línea 248: | ||
break; | break; | ||
} | } | ||
− | |||
− | |||
− | |||
− | |||
} | } | ||
− | |||
} | } | ||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
</source> | </source> | ||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− |
Última revisión de 06:54 14 dic 2023
Sobrecarga
Un concepto muy importante y básico en la programación orientada a objetos. La sobrecarga es una concreción del principio de polimorfismo
|
- Sin embargo este aspecto en php no es del todo intuitivo. No existe la sobrecarga como la entendemos en otros lenguajes.
- No obstante tenemos técnicas para poder simular la sobrecarga.
- Muchas veces es fundamental. Especialmente importante a la hora de sobrecargar el constructor de la clase.
- Para simular la sobrecarga en php, jugamos con el concepto de que una variable que no tenga valor se considera de tipo null.
- Lo vemos con una serie de ejemplos para dejar claro este concepto.
- Tomamos como ejemplo una función:
Ejemplo
| |
function verTipoParametros($a=null,$b=null,$c=null){ echo "Primer parámetro "; var_dump($a); echo "Segundo parámetro "; var_dump($b); echo "Tercer parámetro "; var_dump($c); } </nowiki>
|
- Ahora la invocamos de diferente manera y vemos el resultado:
Invocar sin parámetros reales
| |
echo "Invocando a <strong>verTipoParametros ()</strong><hr / />"; verTipoParametros (); }
|
Invocar con 1 parámetro real
| |
... echo "Invocando a <strong>verTipoParametros (5)</strong><hr />"; verTipoParametros (5); ...
|
Invocar con 2 parámetros reales
| |
... echo "Invocando a <strong>verTipoParametros (5,7)</strong><hr />"; verTipoParametros (5,7); ...
|
Invocar con 3 parámetros reales
| |
... echo "Invocando a <strong> verTipoParametros ('pedro',5,9) </strong><hr />"; verTipoParametros ('pedro',5,9); ...
|
Invocar con 3 parámetro reales uno de ellos un array
| |
... echo "Invocando a <strong> verTipoParametros ([1,4,'maría'],true,'sonia') </strong><hr />"; verTipoParametros ([1,4,'maría'],true,'sonia'); ...
|
Sobrecargando el constructor
- Usando esta forma de trabajar vamos a sobre cargar el constructor de una clase
- Tomamos una clase de tipo Racional. Un número Racional es un objeto que tendrá numerador y denominador
- Ahora a la hora de construir el objeto planteamos la posibilidad de poder instanciar de la siguiente manera:
$r1 = new Racional ("8/5");/* 8/5 */ $r2 = new Racional (5,4); /* 5/6 */ $r3 = new Racional (5); /* 5/1 */ $r4 = new Racional (); /* 1/1 */
- Aquí vemos claramente que necesitamos sobrecargar el constructor para que pueda responder a todas las situaciones
- Aplicando los conceptos vistos antes, lo único que tenemos que hacer en el constructor es ir viendo de qué tipo' son los parámetros.
Tip: Recordar que null también es un tipo
- Vemos que podemos tener 0, 1 o 2 parámetros
- Por lo tanto la función constructora tendrá que tener 2 parámetros
public function __construct($num=1, $den=1) { .... }
- Especificamos el código de cómo se podría hacer
class Racional { private $num; private $den; public function __construct($num=1, $den=1) { //opciones new Racional () =>1/1 //opciones new Racional (5) =>5/1 //opciones new Racional ("5/2") =>5/2 ////opciones new Racional (5,2) =>5/2 //Otra sitiación no se instancia if (is_string($num){ $numero = explode("/",$num) $num = $numero[0]; $den= $numero[1] } $this->num = $num; $this->den = $den; } /*Método para visualizar el objeto como cadena de caracteres*/ public function __toString() { return ($this->num."/".$this->den); } //A continuación los métodos privados para asignar valores private function racionalNum($num) { $this->num = $num; $this->den = 1; } /** * * @param string $num numero racional del tipo "a/b" * hay muchas forma de poder descomponer ese array en dos números */ public function racionalCadena($num) { $this->num = (int) $num; $this->den = substr($num, strpos($num, "/") + 1); } public function racionalVacio() { $this->num = 1; $this->den = 1; } /*En este caso si los valores son incorrectos asigno el racional 1/1 */ public function racionalNumDen($num, $den) { if (is_numeric ($num) && is_numeric($den)){ $this->num = $num; $this->den = $den; }else{ $this->num = 1; $this->den = 1; } } }
- Esta sería un posibilidad, pero debemos de intentar crear un código más compacto y realizar una estratelgia más compacta. El ejemplo anterior lo podríamos compactar de la siguiente manera.
En ella vamos a inicializar los parámetros con un valor que quiero que tengan si no se aporta valor 1 Posteriormente en el código establezco la situación en el caso de que el primer parámetro sea string y asigno los valores a numerador y denominador. Hecho esto, ya hemos considerado todas las opciones, ahora ya solo queda inicializar los atributos con estos valores.
public function __construct($num=1,$den=1){ if (is_string($num)){ $numero= explode("/",$num); $num= $numero[0]; $den= $numero[1]; } $this->num= $num; $this->den= $den; }
- Probamos este constructor con el siguiente código
$a= new Racional(); $b= new Racional(5); $c= new Racional(5,6); $d= new Racional("6/6"); echo "Valor del racional \$a = $a <br />"; echo "Valor del racional \$b = $b <br />"; echo "Valor del racional \$c = $c <br />"; echo "Valor del racional \$d = $d <br />";
- Mostrando los siguientes resultados
Valor del racional $a = 1/1 Valor del racional $b = 5/1 Valor del racional $c = 5/6 Valor del racional $d = 6/6
Sobrecarga con __call(...)
- Otra forma de poder hacer lo mismo es usando el método mágico __call($funcion, $parametros).
Tip: El método mágico __call(..) es ejecutado cuando invocamos a un método que no existe en la clase
- Ahora queremos usar un método llamado asigna que nos permita cambiar el valor de un racional. La forma de aportar el nuevo valor, queremos que sea la misma que la forma de construir el objeto
$r1 = new Racional (); //construye el objeto 1/1 $r1->asigna("6/4"); //Ahora el objeto vale 6/4 $r1->asigna(); //Ahora el objeto vale 1/1 $r1->asigna(8);//Ahora el objeto vale 8/1 $r1->asigna(124, 6);//Ahora el objeto vale 124/6
- La forma de proceder será usando los métodos privados creados anteriormente
- El siguiente código implementa la solución
public function __call($metodo, $argumentos) { if ($metodo == "asigna"){ switch (count($argumentos)){ case 0: $this->racionalVacio(); break; case 2: $this->racionalNumDen($argumentos[0], $argumentos[1]); break; case 1: if (is_int($argumentos[0])) $this->racionalNum($argumentos[0]); else $this->racionalCadena($argumentos[0]); break; } } }