PHP Lambda işlevler Mantıksal değil

7 Cevap php

Note: Ben kişi wiki içine bu makaleyi yoğunlaşmış: http://wiki.chacha102.com/Lambda - Enjoy

PHP Lambda tarzı fonksiyonları ile bazı sıkıntılar yaşıyorum.

İlk olarak, Bu İşleri:

$foo = function(){ echo "bar"; };
$foo();

İkincisi, Bu İşleri:

class Bar{
    public function foo(){
       echo "Bar";
    }

Üçüncü olarak, bu işleri:

$foo = new stdClass;
$foo->bar = function(){ echo "bar"; };
$test = $foo->bar;
$test();

Ancak, bu işe yaramazsa:

$foo = new stdClass;
$foo->bar = function(){ echo "bar"; };
$foo->bar();

Ve, bu işe yaramazsa

class Bar{
    public function foo(){
       echo "Bar";
    }
$foo = new Bar;
$foo->foo = function(){ echo "foo"; };
$foo->foo(); // echo's bar instead of Foo.

Benim Soru Why?, ve nasıl temin ederim ki ikisi de bu:

$foo->bar = function(){ echo "test"; };
$foo->bar();

ve bu

$foo = new Bar;
$foo->bar();

uygun şekilde denir? Ekstra Puan Eğer bu sorun neden belirten belgelerine işaret eğer.

7 Cevap

Bu ilginç bir soru. Bu çalışır:

$a = new stdClass;
$a->foo = function() { echo "bar"; };
$b = $a->foo;
$b(); // echos bars

Eğer dediğiniz gibi ama bu değil:

$a = new stdClass;
$a->foo = function() { echo "bar"; };
$a->foo();

Eğer dinamik üyeleri aramak hangi bir nesneyi istiyorsanız, deneyin:

class A {
  public function __call($func, $args) {
    $f = $this->$func;
    if (is_callable($f)) {
      return call_user_func_array($f, $args);
    }
  }
}

$a = new A;
$a->foo = function() { echo "bar\n"; };
$a->foo2 = function($args) { print_r($args); };
$a->foo();
$a->foo2(array(1 => 2, 3 => 4));

__call() sadece ya yok ya da (örneğin, bu özel konum) erişilebilir değillerdir yöntemleri denir çünkü Ama çağrılabilir yöntemleri bu şekilde yerini alamaz.

Fonksiyonlar ve yöntemler PHP farklı davranılıyor. Sen runkit_method_add() bir sınıf için bir yöntem eklemek için kullanabilirsiniz, ancak ben bir örneğine bir yöntem eklemek için hiçbir şekilde biliyorum.

İlginç bir soru Ben bu çalışması gerekir hiçbir neden göremiyorum rağmen:

class Bar{
    public function foo(){
       echo "Bar";
    }
$foo = new Bar;
$foo->foo = function(){ echo "foo"; };
$foo->foo(); // echo's bar instead of Foo.

I __invoke() ile benzer bir sorun vardı, ve ben de bunu çözmek mümkün değil ettik:

class base {
    function __construct() {
        $this->sub = new sub();
    }

    function __call($m, $a) {
    }
}

class sub {
    function __invoke($a) {
    }
}

$b = new base();
$b->sub('test'); // should trigger base::__call('sub', 'test') or sub::__invoke('test')?

Solution? Never use __invoke()! : P

Bu gerçekleşmesi için alabilir yakın bir özelliği bir kapatma varsa kontrol etmek için __call aşırı kullanılarak olacaktır:

class what {
  function __call($name, $args) {
    $f= $this->$name;
    if ($f instanceof Closure) {
      $f();
    }
  }
}

$foo = new what();
$foo->bar = function(){ echo "bar"; };
$foo->bar();

Rağmen akla docs aşağıdaki not ayı:

Anonymous functions are currently implemented using the Closure class. This is an implementation detail and should not be relied upon.

Reference: Anonymous functions

OP zaten çözümü sundu:

$foo = new stdClass;
$foo->bar = function(){ echo "bar"; };
$test = $foo->bar;
$test();

Özellik adından sonra parantez ekleyerek bir yöntemi çağıran ve bir özellik bir anon işlevi çağrılırken olmadığını PHP söyler, çünkü, yani, bir anon işlevi içeren herhangi bir özellik içsel bir belirsizlik vardır. Bu belirsizliği gidermek için, önce yerel bir değişkene özelliği, saklama ve ardından anon işlevi çağrılırken tarafından ayrılık derecesine eklemeniz gerekir.

Sadece bu içerikleri ne olursa olsun bir özelliği olarak yerine "bir yöntem olarak çağrılabilir bir özellik" olarak sınıf özelliği bakmak ve mülkiyet sonra parantez koymak eğer php gerçek bir sınıf yöntem aramak için gidiyor varsaymak zorundayız.

Benim için bu bir hatadan ziyade bir "cilvesi" gibi görünüyor:

<?php
$t = new stdClass;
$t->a = function() { echo "123"; };
var_dump($t);
echo "<br><br>";
$x = (array)$t;
var_dump($x);
echo "<br><br>";
$x["a"]();
echo "<br><br>";
?>

object(stdClass)#1 (1) { ["a"]=> object(Closure)#2 (0) { } } 

array(1) { ["a"]=> object(Closure)#2 (0) { } } 

123

O orada, ben sadece PHP çalıştırmak bilen olduğunu sanmıyorum.

Bu düşünün:

<?php

class A {

    public $foo

    public function foo() {
        return 'The method foo';
    }

}

$obj = new A;
$obj->foo = function() { return 'The closure foo'; };

var_dump($obj->foo());

Ne demek istiyorsun $ obj-> foo () kapatma veya $ obj-> foo () yöntemi? Bu belirsiz ve PHP yöntemini demek karar verir. Kapatma kullanmak için, ne demek istediğini disambiguate var. Bunu bir yolu yaptın gibi geçici bir değişken kullanarak gereğidir. Başka bir yol kullanmak için call_user_func($obj->foo).

Ben başka kolay bir yol bilmiyorum.