1. 程式人生 > >PHP之回撥、匿名函式與閉包

PHP之回撥、匿名函式與閉包

回撥函式:通俗的解釋就是把函式作為引數傳入進另一個函式中使用;PHP中有許“需求引數為函式”的函式,像array_map,usort,call_user_func_array之類,他們執行傳入的函式,然後直接將結果返回主函式。好處是函式作為值使用起來方便,而且程式碼簡潔,可讀性強。

匿名函式,即沒有一個確定函式名的函式,只能在建立時呼叫或做引數使用。

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

回撥的作用:利用回撥,可以在執行時將與元件的核心任務沒有直接關係的功能插入到元件中。有了元件回撥,你就賦予了他人在你不知道的上下文中擴充套件你的程式碼的權力。

<?php
/*
回撥、匿名函式和閉包
2018.9.16
*/


class Product{
	public $name;
	public $price;

	function __construct( $name, $price ) {
		$this->name = $name;
		$this->price = $price;
	}
}

class ProcessSale {
	 private $callbacks;

	 function registerCallback( $callback) {
	 	if( !is_callable( $callback)){//檢測引數是否為合法的可呼叫結構,測試此函式是否可以被呼叫
	 		throw new Exception( "callback not callable" );
	 	}
	 	$this->callbacks[] = $callback;//這裡為什麼用陣列來儲存?????????????????????????????????????????//
	 }

	 function sale( $product ) {
	 	print "{$product->name}:processing      \n\n";
	 	echo "\n";
	 	foreach ( $this->callbacks as $callback ) {
	 		call_user_func( $callback,  $product);
	 		//通過第一個引數,來呼叫使用者自己的函式
	 	}
	 }
}

class Mailier {
	function doMail ( $product ) {
		print " mailing ({$product->name})\n";
	}
}

class Totalizer {
	static function warnAmount( $amt) {
		$count = 0;
		return function ( $product ) use ( $amt, &$count) {//$count可以用引用來訪問
			$count += $product->price;
			print "   count:$count\n";
			if( $count > $amt ){
				print "  high price reached:{$count }\n";
			}
		};
	}
}

//create_function()建立匿名函式
//$logger = create_function( '$product', 'print "       logging({$product->name})\n";');

//另一種建立匿名函式的方法(推薦使用)
$logger = function( $product ) {
	print "       logging({$product->name})\n";
};

//$processor = new ProcessSale();
//$processor->registerCallback( $logger );

//回撥可以使用函式名甚至是物件引用和方法
//$processor = new ProcessSale();
//$processor->registerCallback( array( new Mailier(), "doMail")  );//陣列形式的回撥以物件做為其第一個元素,以方法名作為其第二單位元素

//use可以讓匿名函式追蹤來自其父作用域的變數
$processor = new ProcessSale();
$processor->registerCallback(Totalizer::warnAmount(8));

$processor->sale( new Product( "shoes", 6 ) );
print "\n";
$processor->sale( new Product( "coffee", 6) );

?>