2017-07-24 3 views
0

Ich erstelle eine Klasse, die Iterator und ArrayAccess implementiert. Die Iterator-Tests sind fehlgeschlagen. Wenn ich eine print_r() on current($object) mache, bekomme ich das zugrunde liegende Array, nicht das erste Objekt.PHP-Iterator-Schnittstelle: current() gibt das zugrunde liegende Array anstelle des ersten Werts zurück

Der folgende Code ist ein Beispiel aus meiner tatsächlichen Klasse, die das Problem veranschaulicht. Dies ist das erste Mal, dass ich Iterator in einer meiner Klassen implementiert habe, also mache ich das wahrscheinlich irgendwo falsch. Was muss ich ändern, damit der Iterator ordnungsgemäß funktioniert?

Code:

class Collection implements \ArrayAccess, \Iterator 
{ 
    private $_array = array(); 

    public function __invoke() { return $this->_array; } 
    public function offsetExists($offset) { return array_key_exists($offset, $this->_array); } 
    public function offsetGet($offset) { return $this->_array[$offset]; } 
    public function offsetSet($offset, $value) { $this->_array[$offset] = $value; } 
    public function offsetUnset($offset) { unset($this->_array[$offset]); } 
    public function current() { return current($this->_array); } 
    public function key() { return key($this->_array); } 
    public function next() { return next($this->_array); } 
    public function rewind() { return reset($this->_array); } 
    public function valid() { return is_null(key($this->_array)); } 
} 

class TemporaryTest extends \PHPUnit\Framework\TestCase 
{ 

    private $_test_object; 

    public function setUp() 
    { 
     $this->_test_object = new Collection(); 
     $this->_test_object['alpha'] = 'blah'; 
     $this->_test_object['beta'] = 'yada'; 
     $this->_test_object['gamma'] = 'woot'; 
    } 

    public function testIteratorOnInternalArray() 
    { 
     $o = $this->_test_object; 
     $a = $o(); 
     $this->assertEquals('blah', current($a)); 
     $this->assertEquals('yada', next($a)); 
     $this->assertEquals('woot', next($a)); 
    } 

    public function testIterator() 
    { 
     print_r(current($this->_test_object)); 
     $this->assertEquals('blah', current($this->_test_object)); 
     $this->assertEquals('yada', next($this->_test_object)); 
     $this->assertEquals('woot', next($this->_test_object)); 
     $this->assertFalse($this->_test_object->valid()); 
     reset($this->_test_object); 
     $this->assertEquals('blah', current($this->_test_object)); 
    } 

    public function testForEach() 
    { 
     $actual = array(); 
     foreach ($this->_test_object as $key => $value) { $actual[$key] = $value; } 
     $this->assertEquals(array('alpha' => 'blah', 'beta' => 'yada','gamma' => 'woot'), $actual); 
    } 
} 

Unit-Test-Ausgang:

.FArray 
(
    [alpha] => blah 
    [beta] => yada 
    [gamma] => woot 
) 
F                 3/3 (100%) 

There were 2 failures: 

1) TemporaryTest::testIterator 
Array (...) does not match expected type "string". 

/Users/mac/Projects/NetShapers/Gears/core/Tests/Unit/TemporaryTest.php:83 

2) TemporaryTest::testForEach 
Failed asserting that two arrays are equal. 
--- Expected 
+++ Actual 
@@ @@ 
Array (
- 'alpha' => 'blah' 
- 'beta' => 'yada' 
- 'gamma' => 'woot' 
) 

/Users/mac/Projects/NetShapers/Gears/core/Tests/Unit/TemporaryTest.php:97 

Antwort

1

Was hast du erwartet?

Wenn Sie current($a) anrufen, rufen Sie tatsächlich Systemfunktion current() auf Ihrer Sammlung, nicht die interne Methode Collection::current().

Gerade calll es so zu bekommen, was Sie wollen:

$this->assertEquals('blah', $a->current()); 

Diese Methoden aufgerufen automatisch vom System würden, wenn Sie Ihre Sammlung in foreach zum Beispiel nutzen könnten.


Weitere Korrekturen nach Kommentar.

Sie haben einen Fehler in valid Methode, deshalb foreach für Sie nicht.

Erklärung sollte so aussehen:

public function valid() 
{ 
    return !is_null(key($this->_array)); 
} 
+0

Ja, das ist genau das, was ich erwarte. Hast du den Teil gesehen, wo auch der 'foreach' Test fehlschlägt? –

+1

@JayBienvenu Ich habe die Antwort mit dem Grund aktualisiert, warum Ihre 'foreach' fehlschlägt –

+0

Also die Antwort ist, dass ich einen Tippfehler in' valid() 'hatte, und' current() 'funktioniert nicht mit Iterator wie' count() 'und andere Funktionen tun? –

Verwandte Themen