2013-01-05 38 views
3

我經歷了Iterator並得到了它應該使用的原因,但我沒有得到的是如何通過foreach調用迭代器對象的迭代方法。通過foreach迭代對象時如何調用Iterator方法

考慮下面的例子來自PHP手冊

class myIterator implements Iterator { 
    private $position = 0; 
    private $array = array(
     "firstelement", 
     "secondelement", 
     "lastelement", 
    ); 

    public function __construct() { 
     $this->position = 0; 
    } 

    function rewind() { 
     var_dump(__METHOD__); 
     $this->position = 0; 
    } 

    function current() { 
     var_dump(__METHOD__); 
     return $this->array[$this->position]; 
    } 

    function key() { 
     var_dump(__METHOD__); 
     return $this->position; 
    } 

    function next() { 
     var_dump(__METHOD__); 
     ++$this->position; 
    } 

    function valid() { 
     var_dump(__METHOD__); 
     return isset($this->array[$this->position]); 
    } 
} 

這裏複製我想,當我使用的foreach如下理解。

如何自動調用myIterator類的方法?

$it = new myIterator; 

foreach($it as $key => $value) { 
    var_dump($key, $value); 
    echo "\n"; 
} 

這裏有什麼魔法?

回答

1

「神奇」,如果你想叫的話,很簡單,PHP有一個定義的行爲,當你試圖重複使用實現了對象Iterator接口。

正如您所知,一個接口只是程序員和應用程序之間的一種合約,它表示將定義某些方法。如果一個類沒有在界面中實現,那麼PHP會拋出一個致命錯誤,程序將終止。這意味着當一個foreach遇到實現接口Iterable的對象時,該對象保證有方法稱爲current,key,next,rewindvalid

除有效之外,這些都是普通數組所存在的所有方法,儘管作爲過程函數而不是對象方法。 (valid對於數組不存在,因爲選擇一個新項目的函數將返回該項目,所以可以說valid已經包含在這些函數中。)這表明在引擎蓋下,foreach循環或多或少地工作在陣列和Iterable對象上的方法相同。

在你的問題中關聯的manual page的示例中,顯示或者至少暗示了對Iterable對象進行迭代的過程,但是我可以看到它可能會造成混淆。下面是該過程的基本解釋:

通常,一個foreach循環將重置指針以獲得一個迭代(注意這裏的小I - 我指的是實現Iterable接口的數組或對象)到第一個位置。換句話說,它會以與倒帶錄像帶相同的方式「倒帶」迭代 - 這一概念可能會在年輕一代中丟失。正如你可能想象的那樣,這是接口需要的方法。

一旦陣列倒帶,foreach嘗試讀取當前選擇的任何元素。使用current方法檢索當前元素的數據,並使用key方法檢索元素的鍵。這些項目放置在您在foreach循環中定義的變量中,循環運行其迭代。

循環迭代完成後,foreach將嘗試使用next方法獲取下一個元素。然後通過執行與最後一段中相同的步驟來處理循環。

在一個Iterable對象,使用前和currentkey,所述foreach循環將調用valid方法讀取的任何數據。如果此方法返回FALSE或PHP認爲與其等效的值(如0或NULL),則foreach假定沒有其他內容可以完全處理和退出循環,並且程序將像平常一樣繼續。