php Iterator 接口详解

大家都知道,数组是可以使用foreach 循环的,我们也可以把一个对象当做数组,做循环操作。

1、对象继承 Iterator 接口

<?php
		class MyIterator implements Iterator{
			private $_d = array('a','b','c','d');
			private $_p = 0;
			public function __construct(){
				$this->_p = 0;
			}
			/**
			 * 返回当前值
			 * 
			 * @see Iterator::current()
			 */
			public function current() {
				var_dump(__METHOD__);
				return $this->_d[$this->_p];
				
			}
		
			/**
			 * 当前索引加1
			 * 
			 * 
			 * @see Iterator::next()
			 */
			public function next() {
				var_dump(__METHOD__);
				$this->_p++;
			}
			/**
			 * 返回当前索引值
			 * 
			 * 
			 * @see Iterator::key()
			 */
			public function key() {
				var_dump(__METHOD__);
				return $this->_p;
				
			}
			/**
			 * 对当前值进行验证
			 * 
			 * @see Iterator::valid()
			 */
			public function valid() {
				var_dump(__METHOD__);
				return isset($this->_d[$this->_p]);
				
			}
			/**
			 * 将数组索引置为0
			 * 
			 * 
			 * @see Iterator::rewind()
			 */
			public function rewind() {
				var_dump(__METHOD__);
				$this->_p = 0;
			}

		}
	$me = new MyIterator();
	foreach($me as $key => $value){
		var_dump($key) . ':' . var_dump($value);
	}
 结果如下图:

让我们分析一下:

1、将对象中数组的索引置为0.

2、验证该索引下是否有值。

3、如果有、返回值。

4、返回索引值。

5、调用next函数,索引值加1.

6、重复2、3、4、步奏。如果验证某索引下没有值,就此中断。

缺点:1、我们需要实现这么多的函数(5个。

             2、上面说到,如果某一索引下没有值,则就此中断了,不在循环,如果我们的数组是这样的private $_d = array('a','b','c','d',8 => 'f');。那么f值就不会被输出。

我们先来解决第一个缺点。

            不实现接口Iterator,实现他的子接口IteratorAggregate

class myData implements IteratorAggregate {
		    public $property1 = "Public property one";
		    public $property2 = "Public property two";
		    public $property3 = "Public property three";
		
		    public function __construct() {
		        $this->property4 = "last property";
		    }
		
		    public function getIterator() {
		        return new ArrayIterator($this);
		    }
		}
		
		$obj = new myData;
		
		foreach($obj as $key => $value) {
		    var_dump($key, $value);
		    echo "\n";
		}

输出如下图:

我们只需实现一个方法getIterator就OK了。是不是简单了。我们也可以直接实现MyIterator ,看看出现什么样的结果,自己去尝试下吧。

解决第二个缺点,这就需要我们来完善MyIterator,保证当索引不连续时,也能输出后面的值。封装的思想啊,大家尝试下吧。

下面再说一说Traversable接口,这个接口中什么样的抽样方法都没有,他是Iterator的父接口。最底层的,这个接口一般不会去实现它,如果非得要实现它,记住两点。

1、必须和Iterator、IteratorAggregate两个接口中的某一个或者两个一起用。

2、IteratorAggregate或者Iterator必须放在Traversable前面。如:class MyIterator implements Iterator,Traversable{}。切记。

上面我们说的都是与循环相关的接口,下面我们就来说一说与赋值、销毁值等相关的接口,那就是ArrayAccess 。

首先,一段代码,实现以下该接口

<?php
		class MyArray implements ArrayAccess{
			
		private $_d = array('a','v','b','d');
			
		/**
		 *  检测某个索引下的值是否存在
		 * 
		 * @see ArrayAccess::offsetExists()
		 */
		public function offsetExists($offset) {
			var_dump(__METHOD__);
			return $this->_d[$offset] !== null;
			
		}
	
		/**
		 * 取得某一索引上的值
		 * 
		 * @see ArrayAccess::offsetGet()
		 */
		public function offsetGet($offset) {
			var_dump(__METHOD__);
			return $this->_d[$offset];
			
		}
	
		/**
		 * 设置某一索引上的值
		 * 
		 * @see ArrayAccess::offsetSet()
		 */
		public function offsetSet($offset, $value) {
			var_dump(__METHOD__);
			$this->_d[$offset] = $value;
			
		}
	
		/**
		 * 销毁某一索引处的值
		 * 
		 * 
		 * @see ArrayAccess::offsetUnset()
		 */
		public function offsetUnset($offset) {
			var_dump(__METHOD__);
			$this->_d[$offset] = null;
		}
			
}
		$me = new MyArray();
		echo $me[0];
		echo "<br />";
		$me[5] = 't' ;
		echo "<br />";
		empty($me[1]) ;
		echo "<br />";
		unset($me[2]) ;
		
结果如图:

一个小问题,留给大家:

如果我们要测试empty($me[10]);会出现什么样的结果呢,大家试下吧。

实现这几个接口完全是为了封装,使其更好的为我们服务。

最后,仅是个人想法,大家共同交流学习。谢谢





  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值