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 相关文章推荐
一个简单的域名注册情况查询程序
Oct 09 PHP
PHP设计模式之调解者模式的深入解析
Jun 13 PHP
常见php数据文件缓存类汇总
Dec 05 PHP
PHP中把对象数组转换成普通数组的方法
Jul 10 PHP
weiphp微信公众平台授权设置
Jan 04 PHP
微信随机生成红包金额算法php版
Jul 21 PHP
php获取远程图片并下载保存到本地的方法分析
Oct 08 PHP
Ubuntu VPS中wordpress网站打开时提示”建立数据库连接错误”的解决办法
Nov 03 PHP
PHP实现无限分类的实现方法
Nov 14 PHP
PHP面向对象之事务脚本模式(详解)
Jun 07 PHP
thinkPHP中U方法加密传递参数功能示例
May 29 PHP
php + WebUploader实现图片批量上传功能
May 06 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函数utf8转gb2312编码
2006/12/21 PHP
解析在PHP中使用mysqli扩展库对mysql的操作
2013/07/03 PHP
PHP Global定义全局变量使用说明
2013/08/15 PHP
Zend Studio使用技巧两则
2016/04/01 PHP
PHP生成图片缩略图类示例
2017/01/12 PHP
CI框架附属类用法分析
2018/12/26 PHP
javascript options属性集合操作代码
2009/12/28 Javascript
javascript sudoku 数独智力游戏生成代码
2010/03/27 Javascript
js检测判断日期大于多少天的方法
2015/05/04 Javascript
jQuery右下角旋转环状菜单特效代码
2015/08/10 Javascript
Bootstrap的popover(弹出框)在append后弹不出(失效)
2017/02/27 Javascript
angular 基于ng-messages的表单验证实例
2017/05/04 Javascript
JS实现静态页面搜索并高亮显示功能完整示例
2017/09/19 Javascript
Bootstrap popover 实现鼠标移入移除显示隐藏功能方法
2018/01/24 Javascript
js遍历添加栏目类添加css 再点击其它删除css【推荐】
2018/06/12 Javascript
vue-cli的build的文件夹下没有dev-server.js文件配置mock数据的方法
2019/04/17 Javascript
Node.js API详解之 module模块用法实例分析
2020/05/13 Javascript
python paramiko模块学习分享
2017/08/23 Python
Windows下的Jupyter Notebook 安装与自定义启动(图文详解)
2018/02/21 Python
Python小进度条显示代码
2019/03/05 Python
python线程的几种创建方式详解
2019/08/29 Python
python 图像处理画一个正弦函数代码实例
2019/09/10 Python
numpy按列连接两个维数不同的数组方式
2019/12/06 Python
Python第三方库的几种安装方式(小结)
2020/04/03 Python
Idea安装python显示无SDK问题解决方案
2020/08/12 Python
设计师家具购买和委托在线市场:Viyet
2016/11/16 全球购物
购买一个高级域名:BuyDomains
2018/03/11 全球购物
文明教师事迹材料
2014/01/16 职场文书
网上开店必备创业计划书
2014/01/26 职场文书
国贸专业自荐信范文
2014/03/02 职场文书
中学校庆方案
2014/03/17 职场文书
关于梦想的演讲稿
2014/05/05 职场文书
主题实践活动总结
2014/05/08 职场文书
2015年党性分析材料
2014/12/19 职场文书
TensorFlow的自动求导原理分析
2021/05/26 Python
关于HTML编码导致的乱码问题
2021/09/04 HTML / CSS