php对象的迭代

PHP的对象支持向数组一样使用foreach来遍历操作对象内部的数据,我们在遍历时就像遍历数组元素一样遍历对象的属性。但注意这个遍历方法受到访问修饰限制的影响。
例如,
定义如下的类:
  1. //PHP代码:
  2. class Student {
  3.     public $name;
  4.     public $tel;
  5.     private $age;
  6.     private $gender;
  7.     public function __construct($name, $tel, $age = 0, $gender = 'secrecy') {
  8.         $this->name = $name;
  9.         $this->tel = $tel;
  10.         $this->age = $age;
  11.         $this->gender = $gender;
  12.     }
  13. }
复制代码
得到学生类 Student 的对象:然后遍历其属性:
  1. //php代码
  2. $stu1 = new Student('令狐冲', '15112345678', 26, 'male');
  3. foreach($stu1 as $property => $value) {
  4.     echo $property, ':', $value;
  5.     echo '
  6. ';
  7. }
  8. //输出结果为:
  9. //name:令狐冲
  10. //tel:15112345678

复制代码
从输出结果上可以看到,我们的对象,就像一个集合类型数据数组一样,可以遍历其内部属性。
但是注意,这种遍历方式也是受访问修饰控制:
因此没有输出 $gender 和 $age这两个属性。
tip:大家可以在类的内部定义一个方法,然后在方法内部尝试遍历该对象,测试是否可以访问到私有的属性?

而且还要注意,遍历对象时,由于对象是引用传递,因此我们遍历的是对象的本身,而不是像遍历数组一样遍历的是数组的拷贝。这也意味着,在foreach遍历对象时,如果操作了对象属性,会影响到我们遍历的过程的:测试下看看:
  1. //PHP代码
  2. $stu1 = new Student('令狐冲', '15112345678', 26, 'male');
  3. foreach($stu1 as $property => $value) {
  4.     //遍历时为$stu1对象增加了一个属性
  5.     $stu1->subject[] = mt_rand(1,9);
  6.     echo $property, ':'; print_r($value);
  7.     echo '
  8. ';
  9. }
  10. //输出结果:
  11. //name:令狐冲
  12. //tel:15112345678
  13. //subject:Array
  14. (
  15.     [0] => 3
  16.     [1] => 8
  17. )

复制代码
注意上面的结果,遍历的次数为3次,说明我们增加的属性也是需要遍历的。(想想数组来)

而且在foreach时,也支持值的引用传递,例如:
  1. //PHP代码
  2. foreach($stu1 as $property => &$value) {
  3.     if($property == 'tel') {
  4.         //修改$value
  5.         $value = '13887654321';
  6.     }
  7. }
  8. var_dump($stu1);
  9. //输出结果:
  10. //object(Student)#1 (4) {
  11.   ["name"]=>
  12.   string(9) "令狐冲"
  13.   ["tel"]=>
  14.   &string(11) "<b>13887654321"</b>
  15.   ["age":"Student":private]=>
  16.   int(26)
  17.   ["gender":"Student":private]=>
  18.   string(4) "male"
  19. }
复制代码
注意输出结果中的tel属性,被改为了新值。

以上就是使用 foreach 的语句结构完成对对象属性的遍历。
但是上面的遍历,不能灵活控制我们需要遍历到的属性,上面的遍历就如同遍历数组一样,那么对象的处理数据的能力就被放弃了,与直接用数组的区别就不是很大了吧!

我们还可以使用定制性更强的遍历对象的方式:
类通过实现内置接口Iterator来实现迭代属性的目的:
php内置了一个接口 Iterator,我们可以通过实现这个接口,让我们的对象有能力自己定义对象的遍历过程:
先看看这个接口的结构吧:
  1. //PHP代码
  2. Iterator extends Traversable {
  3.     //获得当前遍历到的属性值的方法, return mixed
  4.     public current ();
  5.     //获得当前遍历到的属性名的方法, return scalar
  6.     public key ();
  7.     //向下移动需要遍历的位置 return void
  8.     public next ();
  9.     //重置移动的位置,return void
  10.     public rewind ();
  11.     //验证当前位置是否有效的方法,return bool
  12.     public valid ();
  13. }
复制代码
当一个类实现了Iterator接口后,在foreach遍历这个类实例化的对象时,会按照如下的执行流程执行以上的方法: Iterator内方法执行流程
2012-12-30 00:31 上传
下载附件 (25.36 KB)
Iterator内方法执行流程

此时 我们就可以通过实现Iterator接口来按照我们的需求遍历我们的对象:
例如,假设我们有一个学些小组类,班级内有保存了很多学生:
  1. //PHP代码:
  2. class Team {
  3.     private $stus;

  4.     public function __construct() {
  5.         $this->stus = array();
  6.     }
  7.     public function addStu($stu) {
  8.         $this->stus[] = new Student($stu['name'], $stu['tel'], $stu['age'], $stu['gender']);
  9.     }
  10. }
  11. //实例化对象,并添加5个学生
  12. $team = new Team();
  13. $team->addStu(array('name'=>'令狐冲', 'tel'=>'131123456789', 'age'=>24, 'gender'=>'male'));
  14. $team->addStu(array('name'=>'仪琳', 'tel'=>'131321231232', 'age'=>22, 'gender'=>'female'));
  15. $team->addStu(array('name'=>'岳不群', 'tel'=>'13156784321', 'age'=>37, 'gender'=>'male'));
  16. $team->addStu(array('name'=>'陆猴儿', 'tel'=>'13155667788', 'age'=>23, 'gender'=>'male'));
  17. $team->addStu(array('name'=>'岳灵珊', 'tel'=>'13112343121', 'age'=>21, 'gender'=>'female'));
复制代码
现在 我们的小组对象$team就有一个私有属性$stus,保存组内的所有学生信息:
此时我们如果需要遍历$team,遍历的结果为输出组内所有学生的姓名,此时仅仅使用foreach就不行了。就可以通过实现Iterator来实现:
  1. //php代码
  2. class Team implements Iterator{
  3.     private $stus;
  4.     public function __construct() {
  5.         $this->stus = array();
  6.     }
  7.     public function addStu($stu) {
  8.         $this->stus[] = new Student($stu['name'], $stu['tel'], $stu['age'], $stu['gender']);
  9.     }
  10.     public function rewind() {
  11.         reset($this->stus);
  12.     }
  13.     public function valid() {
  14.         return key($this->stus) !== null;
  15.     }
  16.     public function current() {
  17.         $stu = current($this->stus);
  18.         return $stu->name;//只需要当前对象的姓名
  19.     }
  20.     public function key() {
  21.         return key($this->stus);
  22.     }
  23.     public function next() {
  24.         next($this->stus);
  25.     }
  26. }


复制代码
下面遍历这个$team:
  1. //PHP代码
  2. foreach($team as $name) {
  3.     echo $name, '
  4. ';
  5. }
  6. //得到结果
  7. //令狐冲
  8. //仪琳
  9. //岳不群
  10. //陆猴儿
  11. //岳灵珊
复制代码
此时大家可以发现 按照我们自己需要的遍历方式完成了对象的遍历。

Iterator接口是内置接口,直接就可以使用,在php内有很多迭代器, 都是通过实现这个接口完成。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值