真正优秀的程序员是那些专注于认识、理解、沟通和解决问题的人,你得明白,软件只是用来增加效率的工具而已

使用foreach循环类实例

方法1

通过继承Iterator接口并实现它的相关方法,就可以实现像循环数组一样 来循环类

<?php
/**
 * 类实现foreach的访问
 */

class FileDB implements Iterator
{
    public $val = [];
    public function __construct($array)
    {
        if(is_array($array)){
            $this->val = $array;
        }

    }

    public function current()
    {
        $val = current($this->val);
        return $val;
    }

    public function next()
    {
        $val = next($this->val);
        return $val;
    }
    public function key()
    {
        $key = key($this->val);
        return $key;
    }
    public function valid()
    {
        $key = key($this->val);
        if($key !== null && $key !==false){
            return $key;
        }
        return false;
    }
    public function rewind()
    {
        reset($this->val);
    }

}

$arr = [
    'name' => 'zhangtian',
    'sex'  => 'nan',
    'height' => '189',
];

$obj = new FileDB($arr);
foreach ($obj as $key => $val){
    echo $key."-".$val."\n";
}

方法2

通过继承 IteratorAggregate接口,并实现getIterator方法就可以foreach类实例

<?php

class Test implements IteratorAggregate
{
    public $val;
    public function __construct($arr)
    {
        $this->val = $arr;
    }

    public function getIterator()
    {
        return new ArrayIterator($this->val);
    }

}

$arr = ['zhangtian','weifeng','test'];
$obj = new Test($arr);
var_dump($obj instanceof Iterator);
// 结果为 bool(false)
// 虽然IteratorAggregate可以被当作Iterator使用,但是它不是Iterator

echo count($obj)."\n";
// 结果为 1
// 虽然getIterator的返回对象实现了count方法,
// 但是它不能直接被IteratorAggregate实例使用

echo count($obj->getIterator()); //echo 3
echo "<hr>";
//循环读取数据
foreach ($obj as $key => $val) {
    echo $key . "-" . $val . "\n";
}

IteratorIteratorAggregate的区别和联系

Iterator接口实现是真正并且底层的迭代器,而IteratorAggregate是为了方便类使用Iterator而添加的一个额外接口。它们是两个不同的概念,具体使用的时候应该清楚两者间的差异。差别有以下两点:

  • Iterator接口的实现需要自己手动实现它的5个函数,而IteratorAggregate则不需要这样而只需要实现一个返回Iterator对象的方法。

  • 实现了Iterator接口的类是一个Iterator,除了在foreach语句中使用外还可以在其他需要Iterator的环境中使用。而实现IteratorAggregate接口的类只能用于foreach循环,并且如果它返回的Iterator除了这5个方法外还实现了其他方法,不能通过IteratorAggregate类直接使用,而必须用$iteratorAggregate->getIterator()调用那个Iterator来使用。

实例: FileDb类实现foreach逐行遍历文件内容

<?php
/**
 * 类实现foreach的访问
 */

class FileDB implements Iterator
{
    private $filePath;
    private $fp;
    private $linePoint; //当前行的指针
    public function __construct($filePath)
    {
        $this->filePath = $filePath;
        $this->init();
    }
    public function init()
    {
        $this->linePoint = 0  ;
        if(is_null($this->fp)){
            $this->fp = fopen($this->filePath,'rb');
        }
    }

    /**
     * 当前行的数据
     * @return bool|mixed|string
     */
    public function current()
    {
        return fgets($this->fp);
    }

    /**
     * 下一行的指针位置
     */
    public function next()
    {
        ++$this->linePoint;
    }

    /**
     * 当前的指针位置
     * @return mixed
     */
    public function key()
    {
        return $this->linePoint;
    }

    /**
     * 检查是否读到未见末尾
     * @return bool
     */
    public function valid()
    {
        return $this->linePoint <= count(file($this->filePath));
    }

    /**
     * 重置文件头,指针指向第一行
     */
    public function rewind()
    {
        $this->init();
        $this->next();
    }

}

$obj = new FileDB('a.log');
foreach ($obj as $key => $val){
    echo $key."-".$val."\n";
}

微风小站 » 使用foreach循环类实例
分享到: 更多 (0)

评论 抢沙发

评论前必须登录!