天天看點

use在Java中什麼意思_在PHP中,什麼是閉包?為什麼要使用“ use”辨別符?

我正在檢查一些PHP 5.3.0功能,并在網站上遇到了一些看起來很有趣的代碼:

public function getTotal($tax)

{

$total = 0.00;

$callback =

function ($quantity, $product) use ($tax, &$total)

{

$pricePerItem = constant(__CLASS__ . "::PRICE_" .

strtoupper($product));

$total += ($pricePerItem * $quantity) * ($tax + 1.0);

};

array_walk($this->products, $callback);

return round($total, 2);

}

作為匿名函數的例子之一。

有人知道嗎? 有檔案嗎? 而且看起來很邪惡,應該使用它嗎?

#1樓

一個簡單的答案。

function ($quantity) use ($tax, &$total) { .. };

閉包是配置設定給變量的函數,是以您可以傳遞它

閉包是一個單獨的命名空間,通常,您不能通路此命名空間之外定義的變量。 使用關鍵字:

use允許您通路(使用)閉包内部的後續變量。

使用是早期綁定。 這意味着在定義閉包時将複制變量值。 是以,在閉包内部修改$tax不會産生外部影響,除非它像對象一樣是指針。

您可以像使用&$total一樣将變量作為指針傳遞。 這樣,修改$total的值确實具有外部效果,原始變量的值會更改。

在閉包内部定義的變量也不能從閉包外部通路。

閉合和功能具有相同的速度。 是的,您可以在所有腳本中使用它們。

正如@Mytskine 指出的那樣 ,最好的深入解釋可能是針對閉包的RFC 。 (為此投票給他。)

#2樓

這就是PHP表示閉包的方式 。 這根本不是邪惡的,實際上它是強大而有用的。

基本上,這意味着您允許匿名函數在其作用域之外“捕獲”局部變量(在本例中$tax和對$total的引用)并保留其值(或在$total的情況下,引用為( $total本身)作為匿名函數本身内的狀态。

#3樓

封口很漂亮! 它們解決了匿名函數帶來的許多問題,并使真正優雅的代碼成為可能(至少在我們談論php時)。

javascript程式員一直在使用閉包,有時甚至不知道閉包,因為綁定變量未明确定義-這就是php中“ use”的含義。

有比以上示例更好的真實示例。 假設您必須按子值對多元數組進行排序,但是鍵會發生變化。

function generateComparisonFunctionForKey($key) {

return function ($left, $right) use ($key) {

if ($left[$key] == $right[$key])

return 0;

else

return ($left[$key] < $right[$key]) ? -1 : 1;

};

}

$myArray = array(

array('name' => 'Alex', 'age' => 70),

array('name' => 'Enrico', 'age' => 25)

);

$sortByName = generateComparisonFunctionForKey('name');

$sortByAge = generateComparisonFunctionForKey('age');

usort($myArray, $sortByName);

usort($myArray, $sortByAge);

?>

警告:未經測試的代碼(我沒有在atm上安裝php5.3),但它看起來應該像這樣。

有一個缺點:如果您面對閉包的話,許多php開發人員可能會有些無奈。

為了進一步了解閉包的好處,我再舉一個例子-這次使用javascript。 問題之一是範圍和浏覽器固有的異步性。 特别是關于window.setTimeout(); (或-interval)。 是以,您将一個函數傳遞給setTimeout,但實際上不能給出任何參數,因為提供參數會執行代碼!

function getFunctionTextInASecond(value) {

return function () {

document.getElementsByName('body')[0].innerHTML = value; // "value" is the bound variable!

}

}

var textToDisplay = prompt('text to show in a second', 'foo bar');

// this returns a function that sets the bodys innerHTML to the prompted value

var myFunction = getFunctionTextInASecond(textToDisplay);

window.setTimeout(myFunction, 1000);

myFunction傳回帶有某種預定義參數的函數!

老實說,自5.3起,我更喜歡php和匿名函數/閉包。 命名空間可能更重要, 但它們卻不那麼性感 。

#4樓

Zupa在解釋“使用”的閉包以及EarlyBinding和引用“已使用”變量之間的差別方面做得非常出色。

是以,我制作了一個帶有早期綁定變量(=複制)的代碼示例:

$a = 1;

$b = 2;

$closureExampleEarlyBinding = function() use ($a, $b){

$a++;

$b++;

echo "Inside \$closureExampleEarlyBinding() \$a = ".$a."

";

echo "Inside \$closureExampleEarlyBinding() \$b = ".$b."

";

};

echo "Before executing \$closureExampleEarlyBinding() \$a = ".$a."

";

echo "Before executing \$closureExampleEarlyBinding() \$b = ".$b."

";

$closureExampleEarlyBinding();

echo "After executing \$closureExampleEarlyBinding() \$a = ".$a."

";

echo "After executing \$closureExampleEarlyBinding() \$b = ".$b."

";

?>

引用變量的示例(注意變量前的“&”字元);

$a = 1;

$b = 2;

$closureExampleReferencing = function() use (&$a, &$b){

$a++;

$b++;

echo "Inside \$closureExampleReferencing() \$a = ".$a."

";

echo "Inside \$closureExampleReferencing() \$b = ".$b."

";

};

echo "Before executing \$closureExampleReferencing() \$a = ".$a."

";

echo "Before executing \$closureExampleReferencing() \$b = ".$b."

";

$closureExampleReferencing();

echo "After executing \$closureExampleReferencing() \$a = ".$a."

";

echo "After executing \$closureExampleReferencing() \$b = ".$b."

";

?>

#5樓

function () use () {}類似于PHP的閉包。

如果不use ,函數将無法通路父作用域變量

$s = "hello";

$f = function () {

echo $s;

};

$f(); // Notice: Undefined variable: s

$s = "hello";

$f = function () use ($s) {

echo $s;

};

$f(); // hello

use變量的值來自定義函數時的值,而不是調用時的值

$s = "hello";

$f = function () use ($s) {

echo $s;

};

$s = "how are you?";

$f(); // hello

與&一起use變量按引用

$s = "hello";

$f = function () use (&$s) {

echo $s;

};

$s = "how are you?";

$f(); // how are you?