Plantilla:PHP/Sobrecarga

De WikiEducator
Saltar a: navegación, buscar

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
{{{1}}}



  • 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 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=null, $den=null) {
 ....
}
  • Especificamos el código do cómo se podría hacer
class Racional {
 
    private $num;
    private $den;
 
    public function __construct($num=null, $den=null) {
        //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->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

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;
            }
        }
    }