遍历一个对象
常见于foreach遍历,对象的可见属性会被遍历。属性名为key,值为value。
可见属性:就是可以当前上下文可以访问的该对象的属性。例如在一个类的外部创建一个该类的实例,foreach遍历该实例对象,可遍历的只有public属性。在该类的内部遍历$this,那么就可遍历的是所有public ,protected,private属性。
(静态属性不属于对象,因此不可遍历)
//为了简洁,我用匿名类来创建对象,匿名类的写法在php7+开始支持。
$obj = new class{
public $a = 'AAA';
public $b = 'BBB';
protected $c = 'CCC';
private $d = 'DDD';
public static $e = 'EEE';
//内部的遍历
public function giao(){
foreach($this as $key => $value){
print "key:$key value:$value\n";
}
}
};
//外部的遍历
foreach($obj as $key => $value){
print "key:$key value:$value\n";
}
//输出 key:a value:AAA
key:b value:BBB
//调用内部的遍历方法
$obj->giao();
//输出key:a value:AAA
key:b value:BBB
key:c value:CCC
key:d value:DDD
迭代器接口Iterator
Iterator接口的作用是提供了自定义遍历方式。
该接口有五个方法。
下面是这个接口的官方摘要。
Iterator extends Traversable {
/* 方法 */
abstract public current ( void ) : mixed //返回当前元素
abstract public key ( void ) : scalar //返回当前元素的键
abstract public next ( void ) : void //向前移动到下一个元素
abstract public rewind ( void ) : void //返回到迭代器的第一个元素
abstract public valid ( void ) : bool //检查当前位置是否有效
}
这五个方法的设计目的就是为了实现其后面文字注释的功能(当然你也可以不实现这些功能)。
迭代器接口Iterator的使用
类A实现Iterator接口后,创建这个A类的实例对象,然后foreach遍历这个对象,那么这个foreach的效果将取决于你在实现接口时定义的五个方法。这常常用于给类A传入一个想要遍历的数组,然后foreach遍历这个类A的实例。实现自定义的遍历效果。
以下面官方的例子讲解这五个方法的调用顺序和所起到的作用。
//一个想要遍历的数组。
$data = array('a'=>'AAA','b'=>'BBB','c'=>'CCC');
//一个实现了Iterator接口的匿名类,$data将会作为参数传递到构造方法中。
$obj = new class($data) implements Iterator{
private $arr = array();
public function __construct($arr){
$this->arr = $arr;
}
public function rewind() {
echo "rewinding\n";
reset($this->arr);//将数组指针指向数组第一个单元。
}
public function current() {
$var = current($this->arr);
echo "current: $var\n";
return $var;
}
public function key() {
$var = key($this->arr);
echo "key: $var\n";
return $var;
}
public function next() {
$var = next($this->arr);
echo "next: $var\n";
return $var;
}
//valid方法要返回一个bool值,该值为true,会继续循环。为false,则循环结束
public function valid() {
$var = $this->current() !== false;
echo "valid: {$var}\n";
return $var;
}
};
foreach ($obj as $key =>$value){}
//输出 rewinding
current: AAA
valid: 1
current: AAA
key: a
next: BBB
current: BBB
valid: 1
current: BBB
key: b
next: CCC
current: CCC
valid: 1
current: CCC
key: c
next:
current:
valid:
//可以看出,方法的执行顺序为 :
rewind()-> valid()-> current()-> key()-> next()-> valid()-> current()->...
每当rewind()和next()执行后,都会执行valid(),在valid()中判断,并返回bool,可以控制循环继续或停止。