PHP知识、源码、教程、框架、程序分享! -- PHP社区 关于我们 联系我们 联系电话 联系QQ

PHP编程语言中的迭代器

发表时间:2013-09-24 点击:

[本文摘要]:PHP编程 语言中的迭代器 一个对象的属性可以用foreach()循环进行迭代遍历: class MyClass {public $name = Johr;public $sex = male;}$obj = new MyClass();foreach ($obj as $key = $value){print obj[$key] = $value\n;} 运行...

PHP编程语言中的迭代器

一个对象的属性可以用foreach()循环进行迭代遍历:

class MyClass {
	public $name = "Johr";
	public $sex = "male";
}
$obj = new MyClass();
foreach ($obj as $key  => $value){
	print "obj[$key] = $value\n";
}

运行这个脚本得到:

obj[name] = John

obj[sex] = male

但是,如果经常编写面向对象的代码,你的类就不会只是表现为前面例子中一个简单的关键字,值的数组,而会表现为更加复杂的数据,例如一个数据库查询或者配置文件。

PHP 5可以让你用foreach()循环在你的代码中重载迭代行为,使得它按照你的类的设计执行有实际意义的遍历。

注意:PHP 5不仅仅可以让你重载这种行为,而且它还可以让编写扩展的作者重写类似的行为

这已经让迭代器支持多种PHP扩展,例如SimpleXML和SQLite。

为了在你的类中重载迭代器,你需要执行一些PHP预先定义的接口(见图4.2)。

迭代层次的类图
图4.2 迭代层次的类图

任何实现Traversable接口的类都可以用foreach结构遍历。但是,Traversable是一个空的接口而且不能被直接执行;反之,你可以执行Iterator或者IteratorAggregate,它们都是从Traversable继承而来。

主要的接口是Iterator。它定义了你需要执行的方法以便给你的类提供foreach迭代的功能。这些方法应该是公共的,它们都列在表4.1中。

表4.1  Iterator接口

Interface Interator
void rewind() 重新把迭代器指向列表的开始处(这个在执行时并不总是可用的)
mixed current() 返回当前位置的值
mixed key() 返回当前位置的关键字
void next() 把迭代器移动到下一个关键字/值对
bool valid() 返回true/false值,判断是否还有更多的值(在调用current()和key()之前使用)

如果你的类实现了Iterator接口,它将可以用foreach()遍历。下面是一个简单的例子:

class NumberSquared implements Iterator {
	public function __construct ($start, $end)
	{
	  $this->start = $start;
	  $this->end = $end;
	}
	public  function  rewind()
	{
	  $this->cur = $this->start;
	}
	public  function  key()
	{
	  return $this->cur;
	}
	public  function  current ()
	{
	  return pow($this->cur,2);
	}
	public  function next()
	{
	  $this->cur++;
	}
	public  function valid (){
	  return $this->cur <= $this->end;
	}
	private $start, $end;
	private $cur;
}
$obj = new NumberSquared(3,7);
foreach ($obj as $key => $value) {
	print "The square of $key is $value\n";
}

输出是

The square of 3 is 9

The square of 4 is 16

The square of 5 is 25

The square of 6 is 36

The square of 7 is 49

这个例子示范了如何用你自己的方法进行一个类的遍历。在这里,类表现的是整数的平方,而且在给予一个最小值和一个最大值后,迭代遍历这些值将给你数字本身和它的平方值。

目前在许多情况下,你的类本身将表示数据和拥有与这些数据交互的方法。事实上,需要一个迭代器可能不是它的主要目的。另外,当迭代遍历一个对象时,迭代的状态(当前的位置)通常会存储在对象本身,因此不允许迭代的嵌套。因为这两个原因,你可以让你的类实现IteratorAggregate接口从而把类的执行和它的迭代器分离开来。与先前必须定义所有方法不同,你只需要定义一个返回不同类的方法,该对象就为你的类实现了迭代遍历的接口。

你需要实现的public方法是Iterator getlterator(),因为它将返回一个处理这个类的迭代的迭代对象。

通过使用这个把类与其迭代器分离的方法,我们可以用以下方式改写先前的例子:

class NumberSquared implemenes IteratorAggregate {
	public function _constructl$start, $end)
	{
	  $this->start = $start;
	  $this->end = $end;
	}
	public  function  getiterator ()
	{
	  return  new NurnberSquarediterator ($this);
	}
	public function getStart()
	{
	  return $this->start;
	}
	public function getEnd()
	{
	  return $this->end;
	}
	  private $start, $end;
	}
	class NumberSquarediterator implements Iterator{
	function _construct ($obj ){
	  $this->obj = $obj; 
	}
	public function rewind()
	{
	  $this->cur  =  $this->obj ->getStart();
	}
	public function key()
	{
	  return $this->cur;
	}
	public function current(){
	  return pow($this->cur;
	}
	public function next(){
	  $this->cur++;
	}
	public function valid ()
	{
	  return $this->cur <= $this->obj->getEnd();
	}
	private $cur;
	private $obj;
}
$obj  = new NumberSquared(3,7);
foreach ($obj as $key => $value){
	print "The square of $key is $value\n";
}

这个代码的输出与先前的例子的输出是一样的。你可以清楚地看到IteratorAggregate接口可以让你把你的类的主要功能与迭代遍历它需要的方法分离到两个独立的实体中。

在遇到问题时,应该选择适合的迭代方法。是否把迭代器分离到一个单独的类是由类和它的功能决定的。

版权声明:本文系技术人员研究整理的智慧结晶,转载勿用于商业用途,并保留本文链接,侵权必究!

本文链接:http://php.aixc.cn/phpzs/phphanshu/322.html

声明:本站技术及源码均为原创,转载请勿用于商业用途,并注明出处及原文链接,侵权必究。