1. 程式人生 > >20.php回撥、匿名函式、和閉包操作

20.php回撥、匿名函式、和閉包操作

    現在的php是即支援面向物件的語言由支援面向過程的語言,在開發過程中我們往往會混合使用,回撥會讓我們容易將兩種編碼方式做整合,做到優秀的插拔。而閉包操作和回撥都是建立在匿名函式基礎之上的。

<?php
/* 簡單的用於實驗的類  */
class Product{
    public $name;
    public $price;
    
    function __construct($name, $price){
        $this->name = $name;
        $this->price = $price;
    }
}

class ProcessSale{
    //用來存放函式
    private $callbacks = array();
    
    //使用is_callable()在存入陣列之前對函式的可用性進行檢測
    function registerCallback($callback){
        if(!is_callable($callback)){
            throw new Exception("callback not callable!");
        }
        $this->callbacks[] = $callback;
    }
    
    //方便對函式的呼叫
    function sale(Product $product){
        print "{$product->name}:processing<br/>";
        foreach ($this->callbacks as $callback){
            call_user_func($callback, $product);
        }
    } 
}

//被插入的函式
function say($product){
    echo "{$product->name}";
}

$product = new Product('xin', 100);
$process = new ProcessSale();
$process->registerCallback('say');

$process->sale($product);

    那麼匿名函式是什麼樣的呢?

    使用變數存放的型別,注意雖然有分行但是,最後結束還是要使用“;”,另外呼叫的時候要使用變數名,而不是函式名的字串的形式。

//被插入的函式
$say = function ($product){
    echo "{$product->name}";
};
$process->registerCallback($say);

    使用create_function()函式建立的型別。同樣要注意上面提到的兩點。

$say = create_function('$product', 'echo "{$product->name}";');
$process->registerCallback($say);
   下面來說一說閉包的問題。

    所謂的閉包,是一種對作用域進行封裝的方式,使得函式能使用父作用域中的變數。

    有時候我們能將匿名函式直接返回。

class Totalizer{
    static function warnAmount(){
        return function($product){
            echo $product->name;
        };
    }
}
$process->registerCallback(Totalizer::warnAmount());
   現在我們要對商品進行總額計價,並當商品總價格超出某一值時進行提示

   全部程式碼

<?php
/* 簡單的用於實驗的類  */
class Product{
    public $name;
    public $price;
    
    function __construct($name, $price){
        $this->name = $name;
        $this->price = $price;
    }
}

class ProcessSale{
    //用來存放函式
    private $callbacks = array();
    
    //使用is_callable()在存入陣列之前對函式的可用性進行檢測
    function registerCallback($callback){
        if(!is_callable($callback)){
            throw new Exception("callback not callable!");
        }
        $this->callbacks[] = $callback;
    }
    
    //方便對函式的呼叫
    function sale(Product $product){
        print "{$product->name}:processing<br/>";
        foreach ($this->callbacks as $callback){
            call_user_func($callback, $product);
        }
    } 
}

class Totalizer{
    static function warnAmount($amt){
        $count = 0;
        return function($product) use ($amt, &$count){
            $count += $product->price;
            print "all count: $count<br/><br/>";
            if($count > $amt){
                echo "warring!!!!!!";
            }
        };
    }
}

//被插入的函式
/* $say = function ($product){
    echo "{$product->name}";
}; */
$say = create_function('$product', 'echo "{$product->name}";');

$product = new Product('xin', 10);
$process = new ProcessSale();
$process->registerCallback(Totalizer::warnAmount(30));

$process->sale($product);
$process->sale($product);
$process->sale($product);
$process->sale($product);

    Totalizer的warnAmount方法返回一個匿名函式,匿名函式中明確說明要使用類方法中的$amt和$count兩個變數,這就是閉包操作,對父域中的變數的使用。