配列演算子オーバーロードもしくは PHP 5 の配列エミュレート機能全般
正確にはオーバーロードじゃないけど。
PHP でも [] でアクセスできるクラス作れたんだね。
参考
- PHP: ArrayObject - Manual
- 分かりやすい実装例。
- PHP: オブジェクトのイタレーション - Manual
- イテレータについて全般。
- SPL-StandardPHPLibrary
- 詳細なリファレンス。インターフェースのリファレンスが見つからないときに。
<?php /** * ArrayAccess を実装すると [] が使えるようになる。 * * @link http://www.php.net/~helly/php/ext/spl/interfaceArrayAccess.html SPL-StandardPHPLibrary: ArrayAccess Interface Reference */ class A implements ArrayAccess { public function __construct(array $values) { $this->values = $values; } /** * 暗黙的に offsetExists が呼ばれたりはしない。 * & を使ったリファレンス返しはできない。 * * @return mixed */ public function offsetGet($offset) { return $this->values[$offset]; } /** * & を使ったリファレンス渡しはできない。 * $a[] = $value のように呼ばれた場合、 * $offset には null が渡される。 * * @return void */ public function offsetSet($offset, $value) { $this->values[$offset] = $value; } /** * isset で呼ばれる。 * array_key_exists では呼ばれないので注意。 * (この動きどうかと思う) * * @return bool */ public function offsetExists($offset) { return isset($this->values[$offset]); } /** * unset で呼ばれる。 * 暗黙的に offsetExists が呼ばれたりはしない。 * * @return void */ public function offsetUnset($offset) { unset($this->values[$offset]); } } $a = new A(array('a', 'b', 'c' => 'd')); $a[0]; // 'a' $a['c']; // 'd' $a['d'] = 4; $a['d']; // 4 ?>
__toString を持ったクラスのオブジェクトなら、キーに渡せる。
<?php class A implements ArrayAccess { public function offsetSet($offset, $value) { var_dump($offset); // 以下略 } // 以下略 } $a = new A(); class B {} $b = new B(); $a[$b] = 'Error!'; // エラー class C { public function __toString() {} } $c = new C(); $a[$c] = 'OK!'; // object(C)#0 (0) {} /** * A::offsetSet の $offset には、 * __toString の返り値ではなく、オブジェクトそのものが渡される。 */ ?>
配列っぽくしたいなら、これ以外にもインターフェースが用意されている。
概要はこんな感じ。
これ以上のインターフェースの詳細は SPL-StandardPHPLibrary で。
<?php // リストっぽいクラスの基底インターフェース。メソッドは何もない。 interface Traversable {} /** * foreach で使えるようにする。 * * 具体的にはこんな感じで動く。 * 以下の while, for, foreach は全部同じ結果になる。 * * $ite = new SomeIterator(); // Iterator を実装した何らかのクラス * * while ($ite->valid()) { * $key = $ite->key(); * $value = $ite->current(); * echo "$key: $value\n"; * $ite->next(); * } * * $ite->rewind(); * * for ( ; $ite->valid(); $ite->next()) { * $key = $ite->key(); * $value = $ite->current(); * echo "$key: $value\n"; * } * * // foreach は暗黙的に rewind を呼ぶ。 * foreach ($ite as $key => $value) { * echo "$key: $value\n"; * } * // 終わった後は rewind は呼ばない。 * * foreach ($ite as $key => &$value) {} // エラー。イテレータじゃリファレンスは使えない。 */ interface Iterator extends Traversable { /** * 現在の値を得る * * @return mixed */ public function current(); /** * 現在のキー値を得る * * @return string */ public function key(); /** * 次の要素へ移動する。 * * @return void */ public function next(); /** * まだ要素があるかどうか。 * * @return bool */ public function valid(); /** * 先頭に戻す。 * * @return void */ public function rewind(); } // シークできるイテレータ interface SeekableIterator extends Iterator { /** * $position に移動する。 * * @param mixed $position 移動先 * @return void */ public function seek($position); } // count() できる interface Countable { /** * 要素数を返す。 * * empty() では呼ばれないので注意。 * @return int */ public function count(); } /** * foreach で使えるようにする。 * * $obj = new SomeIteratorAggregate(); // IteratorAggregate を実装した何らかのクラス * * foreach ($obj as $key => $value) * は * foreach ($obj->getIterator() as $key => $value) * と同等になる。 */ interface IteratorAggregate extends Traversable { /** * foreach 用のイテレータを返す。 * * @return Iterator */ public functioin getIterator(); } ?>
このへんのリファレンス、公式にないのよな。
仕様かバグかすら分からないというオチ。
追記
とおもったらリファレンスこれか。
http://www.php.net/~helly/php/ext/spl/
何という Java チック。