Diferencia entre revisiones de «Plantilla:PHP/Sobrecarga»

De WikiEducator
Saltar a: navegación, buscar
 
(30 revisiones intermedias por el mismo usuario no mostrado)
Línea 1: Línea 1:
{{TEP}}
+
 
 
===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'''
{{MMF_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 difernte tipo
+
*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.
 
*No obstante tenemos técnicas para poder simular la sobrecarga.
 
*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.
 
*Muchas veces es fundamental. Especialmente importante a la hora de sobrecargar el constructor de la clase.
*Vamos a ver como podemos implementar la sobrecarga en php
+
*Para simular la sobrecarga en '''''php''''', jugamos con el concepto de que una variable que no tenga valor se considera de tipo '''''null'''''.
*Para simular la sobrecarga 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.
*A coninuación una serie de ejemplos para dejar claro este concepto
+
*Tomamos como ejemplo una función:
*Tomamos como ejemplo una función  
+
 
{{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 25: Línea 23:
 
}
 
}
 
</source>
 
</source>
}}<br />
+
</nowiki>
 +
}}
  
*Ahora la invocamos de diferente manera y vemos el resultado
+
<br />
{{MRM_Ejemplo|Title=Invocar sin parámetros reales
+
*Ahora la invocamos de diferente manera y vemos el resultado:
 +
{{MRM_Ejemplo|Title=Invocar sin parámetros reales|
 
<source lang=php>
 
<source lang=php>
 
echo "Invocando a <strong>verTipoParametros ()</strong><hr / />";
 
echo "Invocando a <strong>verTipoParametros ()</strong><hr / />";
Línea 35: Línea 35:
 
</source>
 
</source>
  
*A pesar de que tiene tres parámetros, la invacamos sin parámetros
+
 
*El resultado será que cada parámetro al ejecutar la función será de tipo null con valor null (es un tipo válido en php
+
*A pesar de que tiene tres parámetros, la invocamos sin parámetros
 +
*El resultado será que cada parámetro al ejecutar la función será de tipo '''''null''''' con valor '''''null''''' (es un tipo válido en php):
 
[[Imagen:funcionSinParametrosReales.png]]
 
[[Imagen:funcionSinParametrosReales.png]]
 
}}
 
}}
  
{{MRM_Ejemplo|Title=Invocar con 1 parámetro real
+
{{MRM_Ejemplo|Title=Invocar con 1 parámetro real|
 
<source lang=php>
 
<source lang=php>
 
   ...  
 
   ...  
Línea 54: Línea 55:
  
  
{{MRM_Ejemplo|Title=Invocar con 3 parámetros reales
+
{{MRM_Ejemplo|Title=Invocar con 2 parámetros reales|
 
<source lang=php>
 
<source lang=php>
 
   ...  
 
   ...  
Línea 66: Línea 67:
 
[[Imagen:funcion2ParametrosReal.png]]
 
[[Imagen:funcion2ParametrosReal.png]]
 
}}
 
}}
{{MRM_Ejemplo|Title=Invocar con 3 parámetro reales uno de ellos un array
+
 
 +
{{MRM_Ejemplo|Title=Invocar con 3 parámetros reales|
 
<source lang=php>
 
<source lang=php>
 
   ...  
 
   ...  
echo "Invocando a <strong>verTipoParametros ([1,4,'maria'],true,'sonia')</strong><hr />";
+
echo "Invocando a <strong>
verTipoParametros ([1,4,'maria'],true,'sonia');
+
      verTipoParametros ('pedro',5,9)
 +
      </strong><hr />";
 +
 
 +
verTipoParametros ('pedro',5,9);
 
   ...
 
   ...
 
</source>
 
</source>
*Ahora igualemnte pasamos tres parámetros, pero uno de ellos es un array
+
*Ahora pasamos tres parámetros, como vemos el primero de tipo string y los otros dos enteros
 
*Podemos ver el resultado
 
*Podemos ver el resultado
[[Imagen:funcionParametroRealArray.png]]
+
[[Imagen:funcion3ParametrosReal.png]]
 
}}
 
}}
  
  
{{MRM_Ejemplo|Title=Invocar con 2 parámetro real
+
{{MRM_Ejemplo|Title=Invocar con 3 parámetro reales uno de ellos un '''array'''|
 
<source lang=php>
 
<source lang=php>
 
   ...  
 
   ...  
echo "Invocando a <strong>verTipoParametros ('pedro',5,9)</strong><hr />";
+
echo "Invocando a <strong>
verTipoParametros ('pedro',5,9);
+
      verTipoParametros ([1,4,'maría'],true,'sonia')
 +
      </strong><hr />";
 +
verTipoParametros ([1,4,'maría'],true,'sonia');
 
   ...
 
   ...
 
</source>
 
</source>
*En esta caso invocamos con tres parámetros de diferente tipo
+
*Ahora igualmente pasamos tres parámetros, pero uno de ellos es un array
{{Tipo|PHP lenguaje de tipado dinámico, vemos como el tipo puede cambiar en cada invocación}}
+
*Ahora ya tenemos tres valores diferentes a null en los parámetros reales
+
 
*Podemos ver el resultado
 
*Podemos ver el resultado
[[Imagen:funcion3ParametrosReal.png]]
+
[[Imagen:funcionParametroRealArray.png]]
 
}}
 
}}
  
*Supongamos que en el ejemplo anterior quisiérmos poder instanciar de la siguiente manera los racionales
+
 
 +
====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
 +
[[Imagen:claseRacional.png]]
 +
*Ahora a la hora de construir el objeto planteamos la posibilidad de poder instanciar de la siguiente manera:
 
<source lang=php>
 
<source lang=php>
$a = new racional ("8/5");/*  8/5  */
+
$r1 = new Racional ("8/5");/*  8/5  */
$b = new racional (5,4);  /*  5/6  */
+
$r2 = new Racional (5,4);  /*  5/6  */
$c = new racional (5);    /*  5/1  */
+
$r3 = new Racional (5);    /*  5/1  */
$d = new racional ();    /*  1/1  */
+
$r4 = new Racional ();    /*  1/1  */
 
</source>
 
</source>
*Para esta situación tenemos diferentes estrategias. En este tema vamos a analizar 2:
+
*Aquí vemos claramente que necesitamos sobrecargar el constructor para que pueda responder a todas las situaciones
#sobrecargar en el constructor
+
*Aplicando los conceptos vistos antes, lo  único que tenemos que hacer en el constructor es ir viendo '''''de qué tipo'''' son los parámetros.
#sobrecargar con '''''métodos mágicos'''''
+
;Sobrecargar en el constructor
+
*Una  manera  sencilla es ir viendo '''''de qué tipo'''' son los parámetros
+
 
{{Tip|Recordar que null también es un tipo}}
 
{{Tip|Recordar que null también es un tipo}}
*Vemos que podemos tener 0, 1 o 2 paŕametros
+
*Vemos que podemos tener 0, 1 o 2 parámetros
*Por lo tanto la función constructora tendrá que tener 3 parámetros inicializados por si no le pasamos valores
+
*Por lo tanto la función constructora tendrá que tener 2 parámetros  
 +
 
 
<source lang=php>
 
<source lang=php>
  public function __construct($cadenaOrNum=null, $den = null) {
+
  public function __construct($num=1, $den=1) {
 
  ....
 
  ....
 
}
 
}
 +
 
</source>
 
</source>
{{MRM_Actividad|Title=Sobrecargar el constructor de un racional|
+
*Especificamos el código de cómo se podría hacer
Siguiendo el ejemplo establecido anteriormente realiza un constructor que permita instanciar un objeto de la clase racional de la siguiente manera
+
 
<source lang=php>
 
<source lang=php>
$a = new racional ("8/5");/*  8/5  */
+
class Racional {
$b = new racional (5,4);  /*  5/6  */
+
$c = new racional (5);    /*  5/1  */
+
$d = new racional ();    /*  1/1  */
+
</source>
+
}}
+
<!--
+
  
Vamos a simular la sobre carga de la clase racional
 
 
<source lang=php>
 
<!--
 
<?php
 
/**
 
* Description of racional
 
*
 
* @author manolo
 
*/
 
class racional {
 
    //put your code here
 
    private $numRacional;
 
 
     private $num;
 
     private $num;
 
     private $den;
 
     private $den;
     public function __construct($cadenaOrNum=null, $den = null) {
+
 
         if (is_int($cadenaOrNum)){
+
     public function __construct($num=1, $den=1) {
            if (isset($den))
+
         //opciones new Racional () =>1/1
                $this->racionalNumDen($cadenaOrNum, $den );
+
        //opciones new Racional (5) =>5/1
            else
+
        //opciones new Racional ("5/2") =>5/2
                $this->racionalNum($cadenaOrNum );
+
        ////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]
 
         }
 
         }
         else{
+
         $this->num = $num;  
            if (isset($cadenaOrNum))
+
        $this->den = $den;
                $this->racionalCadena($cadenaOrNum);
+
  }
            else
+
                $this->racionalVacio();
+
        }
+
    }
+
   
+
    private function racionalNumDen($num, $den){
+
        $this->numRacional=$num."/".$den;
+
        $this->num=$num;
+
        $this->den=$den;
+
        $this->convierteNum();
+
    }
+
    private function racionalNum($num){
+
        $this->numRacional=$num."/1";
+
        $this->num=$num;
+
        $this->den=1;
+
        $this->convierteNum();
+
    }
+
    private function racionalCadena($cadenaOrNum){
+
        $this->numRacional=$cadenaOrNum;
+
        $pos = strpos($cadenaOrNum,"/");
+
       
+
        $num=substr($cadenaOrNum,0,$pos);
+
        $den=substr($cadenaOrNum,$pos+1);
+
        $this->num=$num;
+
        $this->den=$den;
+
    }
+
    private function racionalVacio(){
+
        $this->numRacional="1/1";
+
        $this->num=1;
+
        $this->den=1;
+
    }
+
    private function convierteNum(){
+
        settype($this->num, int);
+
        settype($this->den, int);
+
    }
+
   
+
       
+
  
     public function visualiza(){
+
 
         return $this->numRacional;
+
   
 +
    /*Método para visualizar el objeto como cadena de caracteres*/
 +
     public function __toString() {
 +
         return ($this->num."/".$this->den);
 
     }
 
     }
     public function valorRacional(){
+
 
         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;
 
     }
 
     }
     private function simplifica(){
+
     /**
          
+
    *
 +
    * @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);
 
     }
 
     }
     private function suma(racional $num){
+
     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) {
$a=new racional("8/5");
+
        if (is_numeric ($num) && is_numeric($den)){
$b=new racional("6/4");
+
            $this->num = $num;
echo '<br>racional de $a: '. $a->visualiza();
+
            $this->den = $den;
echo '<br>valor de $a: '. $a->valorRacional();
+
        }else{
echo '<br>racional de $b: '. $b->visualiza();
+
            $this->num = 1;
echo '<br>valor de $b: '. $b->valorRacional();
+
            $this->den = 1;
echo"<hr/>";
+
        }
$a=new racional();
+
    }
$b=new racional();
+
}
echo '<br>racional de $a: '. $a->visualiza();
+
echo '<br>valor de $a: '. $a->valorRacional();
+
echo '<br>racional de $b: '. $b->visualiza();
+
echo '<br>valor de $b: '. $b->valorRacional();
+
echo"<hr/>";
+
$a=new racional(8);
+
$b=new racional(4);
+
echo '<br>racional de $a: '. $a->visualiza();
+
echo '<br>valor de $a: '. $a->valorRacional();
+
echo '<br>racional de $b: '. $b->visualiza();
+
echo '<br>valor de $b: '. $b->valorRacional();
+
echo"<hr/>";
+
$a=new racional(124,6);
+
$b=new racional(7,123);
+
echo '<br>racional de $a: '. $a->visualiza();
+
echo '<br>valor de $a: '. $a->valorRacional();
+
echo '<br>racional de $b: '. $b->visualiza();
+
echo '<br>valor de $b: '. $b->valorRacional();
+
 
+
?>
+
 
+
 
</source>
 
</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.
  
}}
 
 
*Código implementado en clase
 
<!--
 
 
<source lang=php>
 
<source lang=php>
<?php
+
public function __construct($num=1,$den=1){
 
+
     if (is_string($num)){
/**
+
         $numero= explode("/",$num);
* Description of racional
+
         $num= $numero[0];
*
+
         $den= $numero[1];
* @author alumno
+
*/
+
class racional {
+
    //put your code here
+
    private $num;
+
    private $den;
+
    private $numRacional;
+
    public function __construct($cadenaOrNum=null, $den = null) {
+
        if (is_null($cadenaOrNum))
+
          $this->racionalVacio();   
+
        else
+
          if (!(is_null($den)))
+
              $this->racionalNumDen($cadenaOrNum, $den );
+
          else
+
              if (is_int($cadenaOrNum))
+
                  $this->racionalNum($cadenaOrNum);
+
              else
+
                  $this->racionalCadena($cadenaOrNum);
+
     }
+
   
+
    //Sobrecargamos el método asigna de modo que se pueda implementar de las siguientes maneras
+
    /*asigna("6/4");
+
      asigna();
+
      asigna(8);
+
      asigna(124, 6);
+
    * */
+
 
+
    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;
+
            }
+
           
+
           
+
           
+
           
+
        }
+
       
+
    }
+
    // caso $a = racional(8,7);
+
    private function racionalNumDen($num, $den ){
+
        $this->num=$num;
+
        $this->den=$den;
+
        $this->numRacional="$num/$den";
+
       
+
    }
+
// caso $a = racional(8);
+
    private function racionalNum($num ){
+
         $this->num=$num;
+
        $this->den=1;
+
        $this->numRacional="$num/1";
+
       
+
    }
+
// caso $a = racional("8/7");
+
    private function racionalCadena($cadena){
+
        $pos = strpos($cadena, "/");
+
        $num = substr($cadena,0, $pos);
+
         $den = substr($cadena ,$pos+1 );
+
       
+
        settype($num, "int");
+
        settype($den, "int");
+
       
+
        $this->num= $num;
+
         $this->den= $den;
+
        $this->numRacional=$cadena;
+
    }
+
// caso $a = racional(); y se inicia con 1/1
+
    private function racionalVacio(){
+
        $this->num=1;
+
        $this->den=1;
+
        $this->numRacional="1/1";
+
       
+
       
+
    }
+
   
+
    public function visualiza(){
+
        echo "<br/>valor del numerador ".$this->num;
+
        echo "<br/>valor del denominador ".$this->den;
+
        echo "<br/>valor del racional ".$this->numRacional;
+
        echo "<br/>valor numerico ".($this->num/$this->den);
+
 
     }
 
     }
 +
    $this->num= $num;
 +
    $this->den= $den;
 
}
 
}
 
 
 
//-------------------------
 
 
 
$a= new racional();
 
$b= new racional(5);
 
$c= new racional(5,6);
 
$d= new racional("6/6");
 
 
$a->visualiza();
 
$b->visualiza();
 
$c->visualiza();
 
$d->visualiza();
 
 
$a->asigna(6000,545);
 
$a->visualiza();
 
$a->asigna("8458/55154");
 
$a->visualiza();
 
$a->asigna(85547);
 
$a->visualiza();
 
$a->asigna();
 
$a->visualiza();
 
?>
 
 
 
 
 
</source>
 
</source>
-->
+
*Probamos este constructor con el siguiente código
;métodos mágicos y la sobrecarga
+
*Hemos visto __construct y __destruct
+
*Vamos a analizar un método mágico para implementar la sobrecarga y exponer su funcionamiento
+
*Ël método '''''__call($nombreFuncion, $argumentos)'''' es un método mágico que se invoca cuando intentamos acceder a un método de la clase y este método no existe
+
*Volvamos a nuestro racional
+
*Supongamos que los métodos de sobrecarga que queremos son los usados en el constructor __construct
+
 
<source lang=php>
 
<source lang=php>
// caso $a = racional(8,7);
+
$a= new Racional();
racionalNumDen($cadenaOrNum, $den );
+
$b= new Racional(5);
// caso $a = racional(8);
+
$c= new Racional(5,6);
racionalNum($cadenaOrNum );
+
$d= new Racional("6/6");
// caso $a = racional("8/7");
+
 
racionalCadena($cadenaOrNum);
+
echo "Valor del racional \$a = $a <br />";
// caso $a = racional(); y se inicia con 1/1
+
echo "Valor del racional \$b  = $b <br />";
racionalVacio();
+
echo "Valor del racional \$= $c <br />";
 +
echo "Valor del racional \$d  = $d <br />";
 
</source>
 
</source>
*Pero imagenimos que nos gustaría que todos tuvieran el mismo nombre, por ejemplo crea().
+
*Mostrando los siguientes resultados
*Vamos a usar el método __call para ello
+
Valor del racional $a <nowiki>=</nowiki> 1/1
*Este método recibe dos argumentos
+
Valor del racional $b <nowiki>=</nowiki> 5/1
# $nombreFuncion es el nombre del método que se invoca
+
Valor del racional $c <nowiki>=</nowiki> 5/6
# $argumentos es un array con los argumentos de la función
+
Valor del racional $d <nowiki>=</nowiki> 6/6
{{MRM_Actividad| vamos a sobrecargar el método asigna() de la clase racional de modo que accepte sobrecarga
+
}}
+
<!--
+
<source lang=php>
+
  
$a=new racional();
+
====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}}
  
$a->asigna("6/4");
+
*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
echo '<br>racional de $a: '. $a->visualiza();
+
echo '<br>valor de $a: '. $a->valorRacional();
+
 
+
echo"<hr/>";
+
$a->asigna();
+
echo '<br>racional de $a: '. $a->visualiza();
+
echo '<br>valor de $a: '. $a->valorRacional();
+
 
+
echo"<hr/>";
+
$a->asigna(8);
+
echo '<br>racional de $a: '. $a->visualiza();
+
echo '<br>valor de $a: '. $a->valorRacional();
+
 
+
echo"<hr/>";
+
$a->asigna(124, 6);
+
echo '<br>racional de $a: '. $a->visualiza();
+
echo '<br>valor de $a: '. $a->valorRacional();
+
</source>
+
<!--
+
 
<source lang=php>
 
<source lang=php>
<?php
+
  $r1 = new Racional (); //construye el objeto 1/1
 
+
   
/*
+
  $r1->asigna("6/4"); //Ahora el objeto vale 6/4
  * To change this license header, choose License Headers in Project Properties.
+
$r1->asigna(); //Ahora el objeto vale 1/1
* To change this template file, choose Tools | Templates
+
$r1->asigna(8);//Ahora el objeto vale 8/1
* and open the template in the editor.
+
$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
  * Description of racional
+
<source lang=php>
  *
+
public function __call($metodo, $argumentos) {
* @author manolo
+
         if ($metodo == "asigna"){
*/
+
class racional {
+
    //put your code here
+
    private $numRacional;
+
    private $num;
+
    private $den;
+
     public function __construct($argumento) {
+
       
+
    }
+
    public function __call($name, $argumentos) {
+
         if ($name=="asigna"){
+
 
             switch (count($argumentos)){
 
             switch (count($argumentos)){
 
                 case 0:
 
                 case 0:
 
                     $this->racionalVacio();
 
                     $this->racionalVacio();
 
                     break;
 
                     break;
                 case 1: //Aquí tenemos dos casos hay que ver el tipo
+
                case 2:
 +
                    $this->racionalNumDen($argumentos[0], $argumentos[1]);
 +
                    break;
 +
                 case 1:
 
                     if (is_int($argumentos[0]))
 
                     if (is_int($argumentos[0]))
 
                         $this->racionalNum($argumentos[0]);
 
                         $this->racionalNum($argumentos[0]);
 
                     else
 
                     else
 
                         $this->racionalCadena($argumentos[0]);
 
                         $this->racionalCadena($argumentos[0]);
                   
 
                    break;
 
                case 2:
 
                    $this->racionalNumDen($argumentos[0],$argumentos[1]);
 
 
                     break;
 
                     break;
 
             }
 
             }
           
 
 
         }
 
         }
   
 
    }
 
   
 
    private function racionalNumDen($num, $den){
 
        $this->numRacional=$num."/".$den;
 
        $this->num=$num;
 
        $this->den=$den;
 
        $this->convierteNum();
 
    }
 
    private function racionalNum($num){
 
        $this->numRacional=$num."/1";
 
        $this->num=$num;
 
        $this->den=1;
 
        $this->convierteNum();
 
    }
 
    private function racionalCadena($cadenaOrNum){
 
        $this->numRacional=$cadenaOrNum;
 
        $pos = strpos($cadenaOrNum,"/");
 
       
 
        $num=substr($cadenaOrNum,0,$pos);
 
        $den=substr($cadenaOrNum,$pos+1);
 
        $this->num=$num;
 
        $this->den=$den;
 
    }
 
    private function racionalVacio(){
 
        $this->numRacional="1/1";
 
        $this->num=1;
 
        $this->den=1;
 
    }
 
    private function convierteNum(){
 
        settype($this->num, int);
 
        settype($this->den, int);
 
    }
 
   
 
       
 
 
    public function visualiza(){
 
        return $this->numRacional;
 
 
     }
 
     }
    public function valorRacional(){
 
        return $this->num/$this->den;
 
    }
 
    private function simplifica(){
 
       
 
    }
 
    private function suma(racional $num){
 
       
 
    }
 
 
}
 
 
$a=new racional();
 
$b=new racional();
 
$a->asigna("8/5");
 
$b->asigna("6/4");
 
echo '<br>racional de $a: '. $a->visualiza();
 
echo '<br>valor de $a: '. $a->valorRacional();
 
echo '<br>racional de $b: '. $b->visualiza();
 
echo '<br>valor de $b: '. $b->valorRacional();
 
echo"<hr/>";
 
$a->asigna();
 
$a->asigna();
 
echo '<br>racional de $a: '. $a->visualiza();
 
echo '<br>valor de $a: '. $a->valorRacional();
 
echo '<br>racional de $b: '. $b->visualiza();
 
echo '<br>valor de $b: '. $b->valorRacional();
 
echo"<hr/>";
 
$a->asigna(8);
 
$b->asigna(4);
 
echo '<br>racional de $a: '. $a->visualiza();
 
echo '<br>valor de $a: '. $a->valorRacional();
 
echo '<br>racional de $b: '. $b->visualiza();
 
echo '<br>valor de $b: '. $b->valorRacional();
 
echo"<hr/>";
 
$a->asigna(124, 6);
 
$b->asigna(124, 6);
 
echo '<br>racional de $a: '. $a->visualiza();
 
echo '<br>valor de $a: '. $a->valorRacional();
 
echo '<br>racional de $b: '. $b->visualiza();
 
echo '<br>valor de $b: '. $b->valorRacional();
 
 
?>
 
 
 
</source>
 
</source>
}}
 
-->
 
==::==
 

Última revisión de 05: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


Icon define.gif
polimorfismo
  • 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


  • 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:


Icon casestudy.gif
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:


Icon casestudy.gif
Invocar sin parámetros reales
echo "Invocando a <strong>verTipoParametros ()</strong><hr / />";
verTipoParametros ();
}


  • A pesar de que tiene tres parámetros, la invocamos sin parámetros
  • El resultado será que cada parámetro al ejecutar la función será de tipo null con valor null (es un tipo válido en php):

FuncionSinParametrosReales.png




Icon casestudy.gif
Invocar con 1 parámetro real
  ... 
  echo "Invocando a <strong>verTipoParametros (5)</strong><hr />";
  verTipoParametros (5);
  ...
  • En esta caso invocamos con un solo parámetro de tipo entero
  • Podemos ver el resultado

Funcion1ParametrosReal.png





Icon casestudy.gif
Invocar con 2 parámetros reales
  ... 
echo "Invocando a <strong>verTipoParametros (5,7)</strong><hr />";
verTipoParametros (5,7);
  ...
  • En esta caso invocamos con dos parámetros de tipo entero
  • Al igual que en caso anterior los parámetros en la función serían 3, dos de ellos con valor de tipo entero, y el tercero con valor y tipo null
  • Podemos ver el resultado

Funcion2ParametrosReal.png




Icon casestudy.gif
Invocar con 3 parámetros reales
  ... 
echo "Invocando a <strong>
      verTipoParametros ('pedro',5,9)
      </strong><hr />";
 
verTipoParametros ('pedro',5,9);
  ...
  • Ahora pasamos tres parámetros, como vemos el primero de tipo string y los otros dos enteros
  • Podemos ver el resultado

Funcion3ParametrosReal.png





Icon casestudy.gif
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');
  ...
  • Ahora igualmente pasamos tres parámetros, pero uno de ellos es un array
  • Podemos ver el resultado

FuncionParametroRealArray.png



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

ClaseRacional.png

  • 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.
Icon present.gif
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).
Icon present.gif
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;
            }
        }
    }