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 生成饼图 三维饼图
Sep 28 PHP
php 随机排序广告的实现代码
May 09 PHP
php获取远程图片的两种 CURL方式和sockets方式获取远程图片
Nov 07 PHP
PHP cdata 处理(详细介绍)
Jul 05 PHP
采用ThinkPHP中F方法实现快速缓存实例
Jun 13 PHP
PHP通过插入mysql数据来实现多机互锁实例
Nov 05 PHP
php限制ip地址范围的方法
Mar 31 PHP
两种php去除二维数组的重复项方法
Nov 04 PHP
解决ThinkPHP下使用上传插件Uploadify浏览器firefox报302错误的方法
Dec 18 PHP
php-beanstalkd消息队列类实例分享
Jul 19 PHP
PHP SFTP实现上传下载功能
Jul 26 PHP
详解thinkphp中的volist标签
Jan 15 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
自己动手,丰衣足食 - 短波框形天线制作
2021/03/01 无线电
php 404错误页面实现代码
2009/06/22 PHP
浅析php创建者模式
2014/11/25 PHP
PHP读取CSV大文件导入数据库的实例
2017/07/24 PHP
jQuery使用手册之三 CSS操作
2007/03/24 Javascript
js+css在交互上的应用
2010/07/18 Javascript
使用原生javascript创建通用表单验证——更锋利的使用dom对象
2011/09/13 Javascript
jquery遍历select元素(实例讲解)
2013/12/31 Javascript
JavaScript驾驭网页-获取网页元素
2016/03/24 Javascript
json对象与数组以及转换成js对象的简单实现方法
2016/06/24 Javascript
JavaScript中boolean类型之三种情景实例代码
2016/11/21 Javascript
vue-dialog的弹出层组件
2020/05/25 Javascript
解决AngualrJS页面刷新导致异常显示问题
2017/04/20 Javascript
jQuery获取复选框选中的当前行的某个字段的值
2017/09/15 jQuery
angular指令笔记ng-options的使用方法
2017/09/18 Javascript
js实现购物车功能
2018/06/12 Javascript
JS实现灯泡开关特效
2020/03/30 Javascript
NodeJS配置CORS实现过程详解
2020/12/02 NodeJs
[01:14]英雄,所敬略同——2018完美盛典宣传视频4K
2018/12/05 DOTA
Python psutil模块简单使用实例
2015/04/28 Python
tensorflow 输出权重到csv或txt的实例
2018/06/14 Python
pycharm 解除默认unittest模式的方法
2018/11/30 Python
解决python给列表里添加字典时被最后一个覆盖的问题
2019/01/21 Python
浅谈PYTHON 关于文件的操作
2019/03/19 Python
python async with和async for的使用
2019/06/20 Python
Django Rest framework解析器和渲染器详解
2019/07/25 Python
python中strip(),lstrip(),rstrip()函数的使用讲解
2020/11/17 Python
凯特王妃父母建立的派对用品网站:Party Pieces
2017/05/28 全球购物
世界上最大的家庭自动化公司:Smarthome
2017/12/20 全球购物
不用游标的SQL语句有哪些
2012/09/07 面试题
如何客观的进行自我评价
2013/12/17 职场文书
师德建设实施方案
2014/03/21 职场文书
志愿者活动总结范文
2014/04/26 职场文书
家长会标语
2014/06/24 职场文书
2019最新婚庆对联集锦!
2019/07/10 职场文书
创业计划书之儿童理发店
2019/09/27 职场文书