php Closure $this做用域問題

今天遇到的個問題,php

  1. 場景 class A 內部 定義了一個static function f1,
  2. 該static func  f1中實例了另外一個class B
  3. f1而後使用B的實例進行setAttribute 操做,其中一個attribute值是一個匿名函數 cf1
  4. cf1依賴一個參數,該參數是 B 的實例
<?php

class A
{
    public static function testClosureScope()
    {
        $objB = (new B)->setAttr1(
            function (){
                self::otherFunc();//todo 此處須要使用當前實例化的B對象做爲參數
            }
        );
    }

    public static function otherFunc(B $objB)
    {
        var_dump($objB);
    }
}

class B
{
    public $attr1;

    /**
     * @return mixed
     */
    public function getAttr1()
    {
        return $this->attr1;
    }

    /**
     * @param mixed $attr1
     */
    public function setAttr1($attr1)
    {
        $this->attr1 = $attr1;

        return $this;
    }


}

問題所在 :上面todo 的地方須要完善,How?閉包

1.傳遞 $this函數

<?php

class A
{
    public static function testClosureScope()
    {
        $objB = (new B)->setAttr1(
            function (){
                self::otherFunc($this);//todo 此處須要使用當前實例化的B對象做爲參數
            }
        );
    }

    public static function otherFunc(B $objB)
    {
        var_dump($objB);
    }
}

ERROR, 想法是好的,可是這個$this,是傳遞不過去的,緣由:this

  • 當前 testClosureScope 方法是staticcode

  • 即便所在方法不是static,$this 也會自動綁定到 Class A的實例,即  Closure中 的 $this會自動bind到定義的類,不必定是調用的類對象

#################################################################################################繼承

解決法遞歸

1.Closure的繼承做用域變量作用域

<?php

class A
{
    public static function testClosureScope()
    {
        $objB = (new B);

        $objB->setAttr1(
            function ()use($objB){
                self::otherFunc($objB);//todo 此處須要使用當前實例化的B對象做爲參數
            }
        );

        return $objB;
    }

    public static function otherFunc(B $objB)
    {
        var_dump($objB);
    }
}

class B
{
    public $attr1;

    /**
     * @return mixed
     */
    public function getAttr1()
    {
        return $this->attr1;
    }

    /**
     * @param mixed $attr1
     */
    public function setAttr1($attr1)
    {
        $this->attr1 = $attr1;

        return $this;
    }
}

$obj  = A::testClosureScope();

$cf = $obj->getAttr1();
$cf();//RECURSION 遞歸引用本身

2. Closure 的 bindToget

<?php

class A
{
    public static function testClosureScope()
    {
        $f = function (){
                self::otherFunc($this);//此處須要使用當前實例化的B對象做爲參數
            };
        $objB = (new B);

        $bindF = $f->bindTo($objB);//閉包綁定至 B實例;因此上面的 $this 纔會生效;注意必定要接收返回值
        $objB->setAttr1($bindF);

        return $objB;
    }

    public static function otherFunc(B $objB)
    {
        var_dump($objB);
    }
}

class B
{
    public $attr1;

    /**
     * @return mixed
     */
    public function getAttr1()
    {
        return $this->attr1;
    }

    /**
     * @param mixed $attr1
     */
    public function setAttr1($attr1)
    {
        $this->attr1 = $attr1;

        return $this;
    }
}

$obj  = A::testClosureScope();

$cf = $obj->getAttr1();
$cf();
相關文章
相關標籤/搜索