答えは「はい」ですが、条件があります。つまり、オブジェクトをトラバースすると、そのパブリック プロパティしか取得できないということです。
// 普通遍历 class A { public $a1 = '1'; public $a2 = '2'; public $a3 = '3'; private $a4 = '4'; protected $a5 = '5'; public $a6 = '6'; public function test() { echo 'test'; } } $a = new A(); foreach ($a as $k => $v) { echo $k, '===', $v, PHP_EOL; } // a1===1 // a2===2 // a3===3 // a6===6
それがメソッドであっても、保護された変数やプライベート変数であっても、トラバースすることはできません。パブリック属性のみをトラバースできます。実際、デザイン パターンについて前に説明した Iterator パターン は、オブジェクト トラバーサルに特に使用されており、PHP は関連するインターフェイスを用意しています。このインターフェイスを実装するだけで済みます。イテレータパターンを完成させることができます。特定の内容については、デザイン パターンに関する以前の一連の記事を参照してください: PHP デザイン パターン イテレータ パターン (推奨: 「PHP ビデオ チュートリアル 」)
// 实现迭代器接口 class B implements Iterator { private $var = []; public function __construct($array) { if (is_array($array)) { $this->var = $array; } } public function rewind() { echo "rewinding\n"; reset($this->var); } public function current() { $var = current($this->var); echo "current: $var\n"; return $var; } public function key() { $var = key($this->var); echo "key: $var\n"; return $var; } public function next() { $var = next($this->var); echo "next: $var\n"; return $var; } public function valid() { $var = $this->current() !== false; echo "valid: {$var}\n"; return $var; } } $b = new B([1, 2, 3, 4]); foreach ($b as $k => $v) { echo $k, '===', $v, PHP_EOL; } // rewinding // current: 1 // valid: 1 // current: 1 // key: 0 // 0===1 // next: 2 // current: 2 // valid: 1 // current: 2 // key: 1 // 1===2 // next: 3 // current: 3 // valid: 1 // current: 3 // key: 2 // 2===3 // next: 4 // current: 4 // valid: 1 // current: 4 // key: 3 // 3===4 // next: // current: // valid:
今日の記事で説明する内容だけであれば、以前にも言いましたが、イテレータ パターンは退屈すぎるので、もっと興味深いアプリケーションを学ばなければなりません。それは、オブジェクトを配列のように操作できるようにすることです。これは実際には、PHP がすでに用意している ArrayAccess インターフェイスを使用しています。
// 让类可以像数组一样操作 class C implements ArrayAccess, IteratorAggregate { private $container = []; public function __construct() { $this->container = [ "one" => 1, "two" => 2, "three" => 3, ]; } public function offsetSet($offset, $value) { if (is_null($offset)) { $this->container[] = $value; } else { $this->container[$offset] = $value; } } public function offsetExists($offset) { return isset($this->container[$offset]); } public function offsetUnset($offset) { unset($this->container[$offset]); } public function offsetGet($offset) { return isset($this->container[$offset]) ? $this->container[$offset] : null; } public function getIterator() { return new B($this->container); } } $c = new C(); var_dump($c); $c['four'] = 4; var_dump($c); $c[] = 5; $c[] = 6; var_dump($c); foreach($c as $k=>$v){ echo $k, '===', $v, PHP_EOL; } // rewinding // current: 1 // valid: 1 // current: 1 // key: one // one===1 // next: 2 // current: 2 // valid: 1 // current: 2 // key: two // two===2 // next: 3 // current: 3 // valid: 1 // current: 3 // key: three // three===3 // next: 4 // current: 4 // valid: 1 // current: 4 // key: four // four===4 // next: 5 // current: 5 // valid: 1 // current: 5 // key: 0 // 0===5 // next: 6 // current: 6 // valid: 1 // current: 6 // key: 1 // 1===6 // next: // current: // valid:
このインターフェイスでは、4 つのメソッドを実装する必要があります:
- offsetSet($offset, $value)、オフセットに従って値を設定します
- offsetExists($ offset )、オフセット
- offsetUnset($offset) に基づいてコンテンツが存在するかどうかを判断、オフセット
- offsetGet($offset) に基づいてコンテンツを削除、オフセットに基づいてコンテンツを取得
ここでのオフセットは、よく添え字と呼ばれるものです。この 4 つのメソッドを実装することで、オブジェクトを配列のように操作することができます。もちろん、日常の開発では、イテレータを含むこれらのオブジェクトを走査する機能を頻繁に使用するわけではありません。通常、次のステップのためにオブジェクトを配列 (配列) obj に直接変換します。ただし、Java、特に JavaBean では、クラス内に独自のコレクション状態を表す独自のオブジェクトとして List