2008-09-28 61 views

回答

61

PHP將會原生支持在封5.3。當你想要一個本地函數只用於一些小的,特定的目的時,閉包是很好的。該RFC for closures給出一個很好的例子:

function replace_spaces ($text) { 
    $replacement = function ($matches) { 
     return str_replace ($matches[1], ' ', ' ').' '; 
    }; 
    return preg_replace_callback ('/(+) /', $replacement, $text); 
} 

這可以讓你在本地定義replacement函數內部replace_spaces(),所以它不是:
1)弄亂全局命名空間
2)製作人3多年來一直困惑爲什麼有一個全球定義的功能只用於一個其他功能

它使事情有條不紊。注意函數本身沒有名字,它只是被定義和分配爲$replacement的引用。

但是要記住,你必須等待PHP 5.3 :)

14

當您將來需要一個執行您現在已經決定的任務的功能時。例如,如果您閱讀了一個配置文件,並且其中一個參數告訴您算法的hash_methodmultiply而不是square,那麼您可以創建一個閉包,在需要散列的地方使用該閉包。

閉包可以在(例如)config_parser();它使用config_parser()(從配置文件中)的本地變量創建一個名爲do_hash_method()的函數。每當調用do_hash_method()時,即使它未在該範圍內調用,它也可以訪問局部範圍config_parser()中的變量。

一個希望好的假設的例子:

function config_parser() 
{ 
    // Do some code here 
    // $hash_method is in config_parser() local scope 
    $hash_method = 'multiply'; 

    if ($hashing_enabled) 
    { 
     function do_hash_method($var) 
     { 
      // $hash_method is from the parent's local scope 
      if ($hash_method == 'multiply') 
       return $var * $var; 
      else 
       return $var^$var; 
     } 
    } 
} 


function hashme($val) 
{ 
    // do_hash_method still knows about $hash_method 
    // even though it's not in the local scope anymore 
    $val = do_hash_method($val) 
} 
+0

我不能簡單地複製粘貼此示例並運行它。首選一個我可以簡單運行的例子。對於不起作用的代碼,爲 – 2013-03-21 08:59:22

+14

-1。 – deceze 2013-05-22 16:41:21

+1

這個答案很糟糕。這是一個毫無意義的陳述:「當你將來需要一個執行你現在決定的任務的功能時。」 – Puzbie 2014-09-11 13:16:29

14
從技術細節

除此之外,閉包是一個基本的前提條件被稱爲面向功能的編程的編程風格。閉包大致用於與在面向對象編程中使用對象相同的東西;它將數據(變量)與一些代碼(一個函數)綁定在一起,然後可以傳遞到其他地方。因此,它們會影響您編寫程序的方式,或者 - 如果您不改變編寫程序的方式 - 它們根本沒有任何影響。

在PHP的上下文中,它們有點奇怪,因爲PHP已經在基於類的面向對象的範例以及早期的過程化範例中佔據重要位置。通常,具有閉包的語言具有完整的詞法範圍。爲了保持向後兼容性,PHP不會得到這個,所以這意味着閉包在這裏會有點不同於其他語言。我想我們還沒有看到他們將如何使用。

8

我喜歡troelskn的帖子提供的上下文。當我想在PHP中使用Dan Udey的例子時,我使用OO策略模式。在我看來,這比引入一個新的全局函數要好得多,這個函數的行爲在運行時確定。

http://en.wikipedia.org/wiki/Strategy_pattern

您也可以撥打使用變量保存在PHP方法名,這是偉大的函數和方法。等等丹的例子別人得會是這樣的:

class ConfigurableEncoder{ 
     private $algorithm = 'multiply'; //default is multiply 

     public function encode($x){ 
       return call_user_func(array($this,$this->algorithm),$x); 
     } 

     public function multiply($x){ 
       return $x * 5; 
     } 

     public function add($x){ 
       return $x + 5; 
     } 

     public function setAlgorithm($algName){ 
       switch(strtolower($algName)){ 
         case 'add': 
           $this->algorithm = 'add'; 
           break; 
         case 'multiply':  //fall through 
         default:    //default is multiply 
           $this->algorithm = 'multiply'; 
           break; 
       } 
     } 
} 

$raw = 5; 
$encoder = new ConfigurableEncoder();       // set to multiply 
echo "raw: $raw\n";            // 5 
echo "multiply: " . $encoder->encode($raw) . "\n";    // 25 
$encoder->setAlgorithm('add'); 
echo "add: " . $encoder->encode($raw) . "\n";     // 10 
當然

,如果你希望它是隨處可見,你可以只讓一切都靜...

1

閉包基本上是爲你寫的定義在一個範圍內,但在另一個環境中運行的功能。 Javascript幫助我理解了這些,因爲它們在JavaScript中被廣泛使用。

在PHP中,由於函數內部的「全局」(或「外部」)變量的範圍和可訪問性不同,所以它們的效率低於JavaScript。然而,從PHP 5.4開始,閉包在對象中運行時可以訪問$ this對象,這使得它們更有效。

這是關閉的關鍵,它應該足以理解上面寫的內容。

這意味着應該可以在某處編寫函數定義,並在函數定義中使用$ this變量,然後將函數定義分配給變量(其他人已經給出了語法的示例),然後傳遞此變量到一個對象並在對象上下文中調用它,然後該函數可以通過$ this訪問和操作對象,就好像它只是它的另一個方法,事實上它並沒有在該對象的類定義中定義,但是別的地方。

如果不是很清楚,那麼不要擔心,一旦開始使用它們就會變得清晰。

0

這裏是在PHP閉包的例子

// Author: [email protected] 
// Publish on: 2017-08-28 

class users 
{ 
    private $users = null; 
    private $i = 5; 

    function __construct(){ 
     // Get users from database 
     $this->users = array('a', 'b', 'c', 'd', 'e', 'f'); 
    } 

    function displayUsers($callback){ 
     for($n=0; $n<=$this->i; $n++){ 
      echo $callback($this->users[$n], $n); 
     } 
    } 

    function showUsers($callback){ 
     return $callback($this->users); 

    } 

    function getUserByID($id, $callback){ 
     $user = isset($this->users[$id]) ? $this->users[$id] : null; 
     return $callback($user); 
    } 

} 

$u = new users(); 

$u->displayUsers(function($username, $userID){ 
    echo "$userID -> $username<br>"; 
}); 

$u->showUsers(function($users){ 
    foreach($users as $user){ 
     echo strtoupper($user).' '; 
    } 

}); 

$x = $u->getUserByID(2, function($user){ 

    return "<h1>$user</h1>"; 
}); 

echo ($x); 

輸出:

0 -> a 
1 -> b 
2 -> c 
3 -> d 
4 -> e 
5 -> f 

A B C D E F 

c 
相關問題