php中如何使对象可以像数组一样进行foreach循环


Posted in PHP onAugust 09, 2013

刚接触到题的时候,我也没有考虑到Iterator模式,试了几个一般想法,失败以后。。。。就直接去翻看了foreach的源码实现,期望发现foreach处理对象的时候是否有什么特殊性,可以做为突破口。

跟踪了半天以后发现了核心逻辑中的一个奇怪的switch:

switch (zend_iterator_unwrap(array, &iter TSRMLS_CC)) {
        default:
        case ZEND_ITER_INVALID:
               .....
               break
        case ZEND_ITER_PLAIN_OBJECT: {
                ......
            break;
     case ZEND_ITER_PLAIN_ARRAY:
            .....
            break;
        case ZEND_ITER_OBJECT:
            ......
            break;
}

从这个结构,我们可以看到,对象分为ZEND_ITER_OBJECT和ZEND_ITER_PLAIN_OBJECT, 这是什么意思呢?
ZEND_API enum zend_object_iterator_kind zend_iterator_unwrap(
    zval *array_ptr, zend_object_iterator **iter TSRMLS_DC)
{
    switch (Z_TYPE_P(array_ptr)) {
        case IS_OBJECT:
            if (Z_OBJ_HT_P(array_ptr) == &iterator_object_handlers) {
                *iter = (zend_object_iterator *)zend_object_store_get_object(array_ptr TSRMLS_CC);
                return ZEND_ITER_OBJECT;
            }
            if (HASH_OF(array_ptr)) {
                return ZEND_ITER_PLAIN_OBJECT;
            }
            return ZEND_ITER_INVALID;
        case IS_ARRAY:
            if (HASH_OF(array_ptr)) {
                return ZEND_ITER_PLAIN_ARRAY;
            }
            return ZEND_ITER_INVALID;
        default:
            return ZEND_ITER_INVALID;
    }
}

这就要讲到PHP的内置接口Iterator了,PHP5开始支持了接口, 并且内置了Iterator接口, 所以如果你定义了一个类,并实现了Iterator接口,那么你的这个类对象就是ZEND_ITER_OBJECT,否则就是ZEND_ITER_PLAIN_OBJECT.

对于ZEND_ITER_PLAIN_OBJECT的类,foreach会通过HASH_OF获取该对象的默认属性数组,然后对该数组进行foreach.

而对于ZEND_ITER_OBJECT的类对象,则会通过调用对象实现的Iterator接口相关函数来进行foreach,iterator接口:

Iterator extends Traversable {
/* 方法 */
abstract public mixed current ( void )
abstract public scalar key ( void )
abstract public void next ( void )
abstract public void rewind ( void )
abstract public boolean valid ( void )
}

所以, 对于这道笔试题, 可以作出如下的答案:
class sample implements Iterator
{
    private $_items = array(1,2,3,4,5,6,7);
    public function __construct() {
                  ;//void
    }
    public function rewind() { reset($this->_items); }
    public function current() { return current($this->_items); }
    public function key() { return key($this->_items); }
    public function next() { return next($this->_items); }
    public function valid() { return ( $this->current() !== false ); }
}
$sa = new sample();
foreach($sa as $key => $val){
    print $key . "=>" .$val;
}

以上代码在我的php 5.3下运行正常。
PHP 相关文章推荐
php代码优化及php相关问题总结
Oct 09 PHP
php中取得文件的后缀名?
Feb 20 PHP
如何使用PHP批量去除文件UTF8 BOM信息
Aug 05 PHP
php读取富文本的时p标签会出现红线是怎么回事
May 13 PHP
php使用str_replace实现输入框回车替换br的方法
Nov 24 PHP
thinkphp文件引用与分支结构用法实例
Nov 26 PHP
php实现概率性随机抽奖代码
Jan 02 PHP
php socket通信简单实现
Nov 18 PHP
php获取今日开始时间和结束时间的方法
Feb 27 PHP
php制作圆形用户头像的实例_自定义封装类源代码
Sep 18 PHP
浅析PHP7的多进程及实例源码
Apr 14 PHP
PHP+Mysql分布式事务与解决方案深入理解
Feb 27 PHP
php接口与接口引用的深入解析
Aug 09 #PHP
解析数组非数字键名引号的必要性
Aug 09 #PHP
php防注入及开发安全详细解析
Aug 09 #PHP
分割GBK中文遭遇乱码的解决方法
Aug 09 #PHP
解析isset与is_null的区别
Aug 09 #PHP
PHP中怎样保持SESSION不过期 原理及方案介绍
Aug 08 #PHP
php中用socket模拟http中post或者get提交数据的示例代码
Aug 08 #PHP
You might like
用PHP生成自己的LOG文件
2006/10/09 PHP
PHP数组内存耗用太多问题的解决方法
2010/04/05 PHP
在Laravel中使用DataTables插件的方法
2018/05/29 PHP
PhpStorm的使用教程(本地运行PHP+远程开发+快捷键)
2020/03/26 PHP
轻量级 JS ToolTip提示效果
2010/07/20 Javascript
JavaScript作用域链示例分享
2014/05/27 Javascript
jQuery中:file选择器用法实例
2015/01/04 Javascript
JS给Textarea文本框添加行号的方法
2015/08/20 Javascript
jQuery右侧选项卡焦点图片轮播特效代码分享
2015/09/05 Javascript
解决js函数闭包内存泄露问题的办法
2016/01/25 Javascript
JavaScript判断数组重复内容的两种方法(推荐)
2016/06/06 Javascript
JS实现队列的先进先出功能示例
2017/05/10 Javascript
JavaScript创建对象_动力节点Java学院整理
2017/06/27 Javascript
利用Javascript实现一套自定义事件机制
2017/12/14 Javascript
js 获取本周、上周、本月、上月、本季度、上季度的开始结束日期
2020/02/01 Javascript
压缩Vue.js打包后的体积方法总结(Vue.js打包后体积过大问题)
2020/02/03 Javascript
vue通过接口直接下载java生成好的Excel表格案例
2020/10/26 Javascript
如何在vue中使用HTML 5 拖放API
2021/01/14 Vue.js
python实现随机密码字典生成器示例
2014/04/09 Python
分享Python文本生成二维码实例
2016/01/06 Python
Django返回json数据用法示例
2016/09/18 Python
Python+tkinter使用80行代码实现一个计算器实例
2018/01/16 Python
win8下python3.4安装和环境配置图文教程
2018/07/31 Python
python 命名规范知识点汇总
2020/02/14 Python
Python web如何在IIS发布应用过程解析
2020/05/27 Python
安装pyecharts1.8.0版本后导入pyecharts模块绘图时报错: “所有图表类型将在 v1.9.0 版本开始强制使用 ChartItem 进行数据项配置 ”的解决方法
2020/08/18 Python
澳大利亚时尚前卫设计师珠宝在线:Amber Sceats
2017/10/04 全球购物
社区文化建设方案
2014/05/02 职场文书
精彩的演讲稿开头
2014/05/08 职场文书
中秋节活动总结
2014/08/29 职场文书
客户答谢会活动方案
2014/08/31 职场文书
车辆转让协议书
2014/09/24 职场文书
老人院义工活动感想
2015/08/07 职场文书
python基于tkinter制作m3u8视频下载工具
2021/04/24 Python
Python道路车道线检测的实现
2021/06/27 Python
拙作再改《我的收音机情缘》
2022/04/05 无线电