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 杂谈《重构-改善既有代码的设计》之四 简化条件表达式
Apr 09 PHP
redis 队列操作的例子(php)
Apr 12 PHP
php调用方法mssql_fetch_row、mssql_fetch_array、mssql_fetch_assoc和mssql_fetch_objcect读取数据的区别
Aug 08 PHP
深入PHP curl参数的详解
Jun 17 PHP
PHP实现批量上传单个文件
Dec 29 PHP
浅析php静态方法与非静态方法的用法区别
May 17 PHP
PHP简单实现DES加密解密的方法
Jul 12 PHP
解决laravel(5.5)访问public报错的问题
Oct 12 PHP
PHP调用QQ互联接口实现QQ登录网站功能示例
Oct 24 PHP
PHP 加密 Password Hashing API基础知识点
Mar 02 PHP
php操作redis数据库常见方法实例总结
Feb 20 PHP
php使用pthreads v3多线程实现抓取新浪新闻信息操作示例
Feb 21 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
动态生成gif格式的图像要注意?
2006/10/09 PHP
php skymvc 一款轻量、简单的php
2011/06/28 PHP
利用ThinkPHP内置的ThinkAjax实现异步传输技术的实现方法
2011/12/19 PHP
php实现的网络相册图片防盗链完美破解方法
2015/07/01 PHP
thinkphp5框架路由原理与用法详解
2020/02/11 PHP
Javascript技术技巧大全(五)
2007/01/22 Javascript
JS 非图片动态loading效果实现代码
2010/04/09 Javascript
浅谈JavaScript中的作用域和闭包问题
2015/07/07 Javascript
跟我学习javascript的prototype,getPrototypeOf和__proto__
2015/11/17 Javascript
通过Tabs方法基于easyUI+bootstrap制作工作站
2016/03/28 Javascript
Vue.js每天必学之指令系统与自定义指令
2016/09/07 Javascript
JS实现Ajax的方法分析
2016/12/20 Javascript
nodejs处理图片的中间件node-images详解
2017/05/08 NodeJs
一文了解vue-router之hash模式和history模式
2019/05/31 Javascript
js中switch语句的学习笔记
2020/03/25 Javascript
pycharm中连接mysql数据库的步骤详解
2017/05/02 Python
python使用numpy读取、保存txt数据的实例
2018/10/14 Python
解决Mac下首次安装pycharm无project interpreter的问题
2018/10/29 Python
OpenCV里的imshow()和Matplotlib.pyplot的imshow()的实现
2019/11/25 Python
tensorflow 初始化未初始化的变量实例
2020/02/06 Python
Django mysqlclient安装和使用详解
2020/09/17 Python
python爬虫调度器用法及实例代码
2020/11/30 Python
Python自动化测试基础必备知识点总结
2021/02/07 Python
图解CSS3制作圆环形进度条的实例教程
2016/05/26 HTML / CSS
Pretty Little Thing爱尔兰:时尚女性服饰
2017/03/27 全球购物
什么是组件架构
2016/05/15 面试题
建筑工程实习自我鉴定
2013/09/19 职场文书
自考生自我鉴定范文
2013/10/01 职场文书
采购类个人求职的自我评价
2014/02/18 职场文书
竞聘演讲稿
2014/04/24 职场文书
俞敏洪励志演讲稿
2014/04/29 职场文书
医德医魂心得体会
2014/09/11 职场文书
办理信用卡收入证明范例
2014/09/13 职场文书
专家推荐信怎么写
2015/03/25 职场文书
离婚财产分割协议书
2015/08/11 职场文书
实用干货:敬酒词大全,帮你应付各种场合
2019/11/21 职场文书