答案是肯定的,但是有个条件,那便是工具的遍历只能得到它的公共属性。
//普通遍历classA{public$a1='1';public$a2='2';public$a3='3';private$a4='4';protected$a5='5';public$a6='6';publicfunctiontest(){echo'test';}}$a=newA();foreach($aas$k=>$v){echo$k,'===',$v,PHP_EOL;}//a1===1//a2===2//a3===3//a6===6
不管是方法还是受保护或者私有的变量,都无法遍历出来。只有公共的属机能力被遍历出来。实在,我们之前在讲设计模式时讲过的迭代器模式便是专门用来进行工具遍历的,而且PHP已经为我们准备好了干系的接口,我们只须要去实现这个接口就可以完成迭代器模式的创建了。详细的内容可以参考之前的设计模式系列文章:PHP设计模式之迭代器模式
//实现迭代器接口classBimplementsIterator{private$var=[];publicfunction__construct($array){if(is_array($array)){$this->var=$array;}}publicfunctionrewind(){echo"rewinding\n";reset($this->var);}publicfunctioncurrent(){$var=current($this->var);echo"current:$var\n";return$var;}publicfunctionkey(){$var=key($this->var);echo"key:$var\n";return$var;}publicfunctionnext(){$var=next($this->var);echo"next:$var\n";return$var;}publicfunctionvalid(){$var=$this->current()!==false;echo"valid:{$var}\n";return$var;}}$b=newB([1,2,3,4]);foreach($bas$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。
//让类可以像数组一样操作classCimplementsArrayAccess,IteratorAggregate{private$container=[];publicfunction__construct(){$this->container=["one"=>1,"two"=>2,"three"=>3,];}publicfunctionoffsetSet($offset,$value){if(is_null($offset)){$this->container[]=$value;}else{$this->container[$offset]=$value;}}publicfunctionoffsetExists($offset){returnisset($this->container[$offset]);}publicfunctionoffsetUnset($offset){unset($this->container[$offset]);}publicfunctionoffsetGet($offset){returnisset($this->container[$offset])?$this->container[$offset]:null;}publicfunctiongetIterator(){returnnewB($this->container);}}$c=newC();var_dump($c);$c['four']=4;var_dump($c);$c[]=5;$c[]=6;var_dump($c);foreach($cas$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:
这个接口须要我们实现四个方法:
offsetSet(\$offset, $value),根据偏移量设置值offsetExists($offset),根据偏移量确定是否存在内容offsetUnset($offset),根据偏移量删除内容offsetGet($offset),根据依稀量获取内容这里的偏移量便是我们常说的下标。通过实现这四个方法,我们就可以像操作数组一样的操为难刁难象。当然,日常开拓中我们可能并不会很常常的利用包括迭代器在内的这些工具遍历的能力。常日我们会直接去将工具转换成数组 (array) obj 来进行下一步的操作。不过,在java中,特殊是JavaBean中会常常在类的内部有一个 List 为自己的工具来表示自身的凑集状态。通过比拟,我们创造PHP也完备可以实现这样的能力,而且利用迭代器和 ArrayAccess 接口还能够更方便的实现类似的能力。这是非常有用的一种知识扩展,或许下一个项目中你就能利用上这些能力哦!
测试代码: https://github.com/zhangyue0503/dev-blog/blob/master/php/201912/source/PHP%E6%80%8E%E4%B9%88%E9%81%8D%E5%8E%86%E5%AF%B9%E8%B1%A1%EF%BC%9F.php
参考文档: https://www.php.net/manual/zh/language.oop5.iterations.php