最近更新: 2007-06-26

SPL~Use ArrayObject and ArrayIterator to Overload Operators of Array

If you want to design a class and make it's behavior as an array, you may extend ArrayObject. Also this new class probably need to use an instance of class which extends ArrayIterator (Note: ArrayIterator is a class, not an interface).

This feature requires PHP 5.

The statement foreach ($arrayobject as $k => $v) {...} means:

$arrayobject->iterator->rewind();
while ($arrayobject->iterator->valid()) {
    $v = $arrayobject->iterator->current();
    $k = $arrayobject->iterator->key();

    ...

    $arrayobject->iterator->next();
}
Note: A native array could be iterate by reference. For example: foreach ($array as $k => &$v). But an instance of ArrayIterator can not do that. Cause the value of iteration is return from method ArrayIterator::current() which prototype is not a reference.

The following codes shows how to overload indexer and foreach structure in PHP5.

<?php
class MyArrayIterator extends ArrayIterator {
    public function rewind() {
        echo "overloading operator rewind: begin to iterate.\n";
        return parent::rewind();
    }

    public function valid() {
        echo "overloading operator valid: every iteration will call once.\n";
        return parent::valid();
    }

    public function current() {
        echo "overloading operator current: foreach (obj as ? => value).\n";
        return parent::current();
    }

    public function key() {
        echo "overloading operator key: foreach (obj as key => ?).\n";
        return parent::key();
    }
    
    public function next() {
        echo "overloading operator next: next iteration.\n";
        return parent::next();
    }
}

class MyArray extends ArrayObject {
    /**
     * It means: $array[] = $v
     */
    public function append($v) {
        echo "overloading setter: obj[]= $v\n";
        return parent::append($v);
    }

    /**
     * It means: $array[$index] = $v
     * Ruby's []= method.
     */
    public function offsetSet($index, $v) {
        echo "overloading setter: obj[$index]= $v\n";
        return parent::offsetSet($index, $v);
    }

    /**
     * It means:  $v = $array[$index]
     * Ruby's [] method.
     */
    public function offsetGet($index) {
        echo "overloading getter: =obj[$index]\n";
        return parent::offsetGet($index);
    }

    /**
     * It means: isset($array[$index])
     */
    public function offsetExists($index) {
        echo "overloading operator of isset: isset(obj[$index])\n";
        return parent::offsetExists($index);
    }

    /**
     * It means: unset($array[$index])
     */
    public function offsetUnset($index) {
        echo "overloading operator of unset: unset(obj[$index])\n";
        return parent::offsetUnset($index);
    }

    /**
     * It means: count($array)
     */
    public function count() {
        echo "overloading operator of count: count(obj)\n";
        return parent::count();
    }
    
    public function getIterator() {
        echo "overloading control structure of foreach: foreach(obj as)\n";
        //return parent::getIterator();

        return ($this->iterator = new MyArrayIterator(parent::getIterator()));
    }
}

$array = array('1' => 'one',
               '2' => 'two',
               '3' => 'three');

$arrayobject = new MyArray($array);

echo $arrayobject[1], "\n";
$arrayobject[] = 'four';
$arrayobject[5] = 'five';
echo count($arrayobject), "\n";
echo isset($arrayobject[4]), "\n";
unset($arrayobject[3]);

foreach ($arrayobject as $k => $v) {
    echo "iteration: $k = $v\n";
}

print_r($array);
?>
相關文章
樂多舊網址: http://blog.roodo.com/rocksaying/archives/3532653.html