Diferencia entre revisiones de «Plantilla:PHP/Sobrecarga»

De WikiEducator
Saltar a: navegación, buscar
(Deshecha la revisión 21046 de ManuelRomero (disc.))
Línea 97: Línea 97:
 
*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 poderñp  instanciar de la siguiente manera:
=======================================
+
*Supongamos que en el ejemplo anterior quisiéramos poder instanciar de la siguiente manera los racionales
+
 
<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 parámetros
 
*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, $den) {
 
  ....
 
  ....
 
}
 
}
 
</source>
 
</source>
{{MRM_Actividad|Title=Sobrecargar el constructor de un racional|
+
*Especificamos el código do 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>
+
$a = new racional ("8/5");/*  8/5  */
+
$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>
 
<source lang=php>
<!--
+
class Racional {
<?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, $den) {
             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_null($den)) {
 +
             switch (is_numeric($num)) {
 +
                 case true:
 +
                    $this->asigna(racionalNum($num);
 +
                    break;
 +
                case false:
 +
                    if (is_null($num)){
 +
                        $this->racionalVacio();
 +
                        break;
 +
                    }
 +
                    else {
 +
                        $this->racionalCadena($num);
 +
                        break;
 +
                    }
 +
             }
 +
        }else {
 +
            $this->racionalNumDen($num,$den);
 
         }
 
         }
        else{
 
            if (isset($cadenaOrNum))
 
                $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();
+
</source>
echo '<br>valor de $a: '. $a->valorRacional();
+
*Probamos este constructor con el siguiente código
echo '<br>racional de $b: '. $b->visualiza();
+
<source lang=php>
echo '<br>valor de $b: '. $b->valorRacional();
+
$a= new Racional();
echo"<hr/>";
+
$b= new Racional(5);
$a=new racional(8);
+
$c= new Racional(5,6);
$b=new racional(4);
+
$d= new Racional("6/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();
+
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();
+
 
+
?>
+
  
 +
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 />";
 
</source>
 
</source>
 +
*Mostrando los siguientes resultados
 +
Valor del racional $a <nowiki>=</nowiki> 1/1
 +
Valor del racional $b <nowiki>=</nowiki> 5/1
 +
Valor del racional $c <nowiki>=</nowiki> 5/6
 +
Valor del racional $d <nowiki>=</nowiki> 6/6
  
 
}}
 
}}

Revisión de 01:07 2 dic 2016

Road Works.svg Trabajo en proceso, espera cambios frecuentes. Tu ayuda y retroalimentación son bienvenidos.
Ver página de charlas.
Road Works.svg


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 difernte 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,$b,$c){
    echo "Primer parámetro ";
    var_dump($a);
    echo "Segundo parámetro ";
    var_dump($b);
    echo "Tercer parámetro ";
    var_dump($c);
}



  • 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ámetro 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 igualemente 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ñp 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, $den) {
 ....
}
  • Especificamos el código do cómo se podría hacer
class Racional {
 
    private $num;
    private $den;
 
    public function __construct($num, $den) {
        //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_null($den)) {
            switch (is_numeric($num)) {
                case true:
                    $this->asigna(racionalNum($num);
                    break;
                case false:
                    if (is_null($num)){
                        $this->racionalVacio();
                        break;
                    }
                     else {
                        $this->racionalCadena($num);
                        break;
                     }
            }
        }else {
            $this->racionalNumDen($num,$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;
        }
    }
 }
  • 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 

}}

  • Código implementado en clase
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
// caso $a = racional(8,7);
racionalNumDen($cadenaOrNum, $den );
// caso $a = racional(8);
racionalNum($cadenaOrNum );
// caso $a = racional("8/7");
racionalCadena($cadenaOrNum);
// caso $a = racional(); y se inicia con 1/1
racionalVacio();
  • Pero imagenimos que nos gustaría que todos tuvieran el mismo nombre, por ejemplo crea().
  • Vamos a usar el método __call para ello
  • Este método recibe dos argumentos
  1. $nombreFuncion es el nombre del método que se invoca
  2. $argumentos es un array con los argumentos de la función


Icon activity.jpg
Actividad
vamos a sobrecargar el método asigna() de la clase racional de modo que accepte sobrecarga




::