Saltar al contenido

PHP: Sugerencia de tipo – Diferencia entre `Closure` y` Callable`

Solución:

La diferencia es que un Closure debe ser una función anónima, donde callable también puede ser una función normal.

Puede ver / probar esto con el ejemplo a continuación y verá que obtendrá un error para el primero:

function callFunc1(Closure $closure) {
    $closure();
}

function callFunc2(Callable $callback) {
    $callback();
}

function xy() {
    echo 'Hello, World!';
}

callFunc1("xy"); // Catchable fatal error: Argument 1 passed to callFunc1() must be an instance of Closure, string given
callFunc2("xy"); // Hello, World!

Entonces, si solo desea escribir una sugerencia, use la función anónima: Closure y si también desea permitir las funciones normales, use callable como sugerencia de tipo.

La principal diferencia entre ellos es que un closure es un clase y callable a escribe.

los callable type acepta cualquier cosa que se pueda llamar:

var_dump(
  is_callable('functionName'),
  is_callable([$myClass, 'methodName']),
  is_callable(function(){})
); // all true

Donde un closure voluntad solamente aceptar una función anónima. Tenga en cuenta que en la versión 7.1 de PHP puede convertir funciones a un cierre como este:
Closure::fromCallable('functionName').


Ejemplo:

namespace foo{
  class bar{
    private $baz = 10;

    function myCallable(callable $cb){$cb()}
    function myClosure(Closure $cb){$cb()} // type hint must refer to global namespace
  }

  function func(){}
  $cb = function(){};
  $fb = new bar;

  $fb->myCallable(function(){});
  $fb->myCallable($cb);
  $fb->myCallable('func');

  $fb->myClosure(function(){});
  $fb->myClosure($cb);
  $fb->myClosure(Closure::fromCallable('func'));
  $fb->myClosure('func'); # TypeError
}

Entonces, ¿por qué usar un closure sobre callable?

Estricidad porque un closure es un objeto que tiene algunos métodos adicionales: call(), bind() y bindto(). Te permiten usar una función declarada fuera de una clase y ejecutarla como si estuviera dentro de una clase:

$inject = function($i){return $this->baz * $i;};
$cb1 = Closure::bind($inject, $fb);
$cb2 = $inject->bindTo($fb);

echo $cb1->call($fb, 2); // 20
echo $cb2(3);            // 30

No le gustaría llamar a métodos en una función normal ya que eso generará errores fatales. Entonces, para eludir eso, tendría que escribir algo como:

if($cb instanceof Closure){}

Hacer esta comprobación cada vez no tiene sentido. Entonces, si desea utilizar esos métodos, indique que el argumento es un closure. De lo contrario, solo use un callback. De esta manera; Se genera un error en la llamada a la función en lugar de su código, lo que hace que sea mucho más fácil de diagnosticar.

En otros comentarios: los closure la clase no se puede extender como su final.

¡Haz clic para puntuar esta entrada!
(Votos: 0 Promedio: 0)


Tags : /

Utiliza Nuestro Buscador

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *