2015-05-21 49 views
3

標準currentkeynext函數似乎忽略迭代器子類方法。如何使Iterator子類方法遵守數組指針函數?

在這個例子中,我只是覆蓋Iterator::current方法返回一個修改過的字符串。看來我的方法與父類有不同的狀態。它不能訪問相同的指針,並且在實例上調用current()時它不會觸發。

<?php 

class DecoratingIterator extends ArrayIterator { 

    public function current(){ 
     return '**'.strtoupper(parent::current()).'**'; 
    } 
} 

$test = new DecoratingIterator(['foo','bar']); 

next($test); 

echo $test->current(),"\n"; 
// prints "**FOO**" 

echo current($test),"\n"; 
// prints "bar" 

我敢肯定,這是預期的行爲,但有沒有辦法讓我的子類方法的工作時,PHP函數調用就可以了?

+1

我不確定,但我認爲'next()'和它的朋友根本不使用接口'Iterator'的方法。它們修改數組的內部指針,而迭代器是保持迭代狀態(通過數組或其他數據結構)的外部類。將函數['next()'](http://php.net/manual/en/function.next.php)的文檔與方法['Iterator :: next()'](http:// php.net/manual/en/iterator.next.php)。迭代器被設計爲使用'foreach',而舊函數current(),next()'有不同的工作方式。 – axiac

+1

一個很好的閱讀:https://nikic.github.io/2012/03/28/Understanding-PHPs-internal-array-implementation.html –

+0

@axiac next和朋友可以使用像ArrayIterator這樣的本地迭代器,但是你'他們的工作方式不同,不應該被稱爲自定義對象。這是讓我困惑的子類怪癖。我把一個小小的Gist顯示出來:https://gist.github.com/timwhitlock/d791a357520f73b4d2f9 – Tim

回答

1

此答案需要安裝APD functions

這樣做的原因是currentkeynext是不是ArrayIterator一部分,即使他們是你仍然會被調用ArrayIterator::current(),它運行在ArrayIterator原來的方法。你需要做的是覆蓋功能current並指示它使用override_function來調用你的新功能。像這樣的東西應該這樣做(注:我沒有測試過)。

rename_function('current', 'original_current'); 
override_function('current', '$obj', 'return override_current($obj);'); 
function override_current($obj) 
{ 
    if ($obj instanceof DecoratingIterator) 
    { 
     return $obj->current(); 
    } 
    else 
    { 
     return original_current($obj); 
    } 
} 
+0

而'override_funtion'是可用的嗎?它是PHP的默認函數嗎? PECL需要安裝嗎? – dbf

+0

@dbf正如我在我的答案中所提到的,您需要APD函數。 – Styphon

+0

它沒有顯示編輯,那麼解決了;) – dbf