参考资料

  1. http://www.laruence.com/2015/05/28/3038.html
  2. http://php.net/manual/zh/class.generator.php
  3. http://www.cnblogs.com/whoamme/p/5039533.html
  4. http://php.net/manual/zh/class.iterator.php


PHP的 yield 关键字是php5.5版本推出的一个特性,算是比较古老的了,其他很多语言中也有类似的特性存在。但是在实际的项目中,目前用到还比较少。网上相关的文章最出名的就是鸟哥的那篇了,但是都不够细致理解起来较为困难,今天我来给大家超详细的介绍一下这个特性。

function gen(){
  while(true){
    yield "gen\n";
  }
}

$gen = gen();

var_dump($gen instanceof Iterator);
echo "hello, world!";

 

如果事先没了解过yield,可能会觉得这段代码一定会进入死循环。但是我们将这段代码直接运行会发现,输出hello, world!,预想的死循环没出现。
究竟是什么样的力量,征服了while(true)呢,接下来就带大家一起来领略一下yield关键字的魅力。

首先要从foreach说起,我们都知道对象,数组和对象可以被foreach语法遍历,数字和字符串缺不行。其实除了数组和对象之外PHP内部还提供了一个 Iterator 接口,实现了Iterator接口的对象,也是可以被foreach语句遍历,当然跟普通对象的遍历就很不一样了。

以下面的代码为例:

class Number implements Iterator{
  protected $key;
  protected $val;
  protected $count;

  public function __construct(int $count){
    $this->count = $count;
  }

  public function rewind(){
    $this->key = 0;
    $this->val = 0;
  }

  public function next(){
  $this->key += 1;
  $this->val += 2;
  }

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

  public function key(){
  return $this->key + 1;
  }

  public function valid(){
    return $this->key < $this->count;
  }
}


foreach (new Number(5) as $key => $value){
  echo "{$key} - {$value}\n";
}

 

这个例子将输出
    1 - 0
    2 - 2
    3 - 4
    4 - 6
    5 - 8

关于上面的number对象,被遍历的过程。如果是初学者,可能会出现有点懵的情况。为了深入的了解Number对象被遍历的时候内部是怎么工作的,我将代码改了一下,将接口内的每个方法都尽心输出,借此来窥探一下遍历时对象内部方法的的执行情况。

  class Number implements Iterator{  
        protected $i = 1;
        protected $key;
        protected $val;
        protected $count; 
        public function __construct(int $count){
            $this->count = $count;
            echo "第{$this->i}步:对象初始化.\n";
            $this->i++;
        }
        public function rewind(){
            $this->key = 0;
            $this->val = 0;
            echo "第{$this->i}步:rewind()被调用.\n";
            $this->i++;
        }
        public function next(){
            $this->key += 1;
            $this->val += 2;
            echo "第{$this->i}步:next()被调用.\n";
            $this->i++;
        }
        public function current(){
            echo "第{$this->i}步:current()被调用.\n";
            $this->i++;
            return $this->val;
        }
        public function key(){
            echo "第{$this->i}步:key()被调用.\n";
            $this->i++;
            return $this->key;
        }
        public function valid(){
            echo "第{$this->i}步:valid()被调用.\n";
            $this->i++;
            return $this->key < $this->count;
        }
    }

    $number = new Number(5);
    echo "start...\n";
    foreach ($number as $key => $value){
        echo "{$key} - {$value}\n";
    }
    echo "...end...\n";

 

以上代码输出如下

第1步:对象初始化.
start...
第2步:rewind()被调用.
第3步:valid()被调用.
第4步:current()被调用.
第5步:key()被调用.
0 - 0
第6步:next()被调用.
第7步:valid()被调用.
第8步:current()被调用.
第9步:key()被调用.
1 - 2
第10步:next()被调用.
第11步:valid()被调用.
第12步:current()被调用.
第13步:key()被调用.
2 - 4
第14步:next()被调用.
第15步:valid()被调用.
第16步:current()被调用.
第17步:key()被调用.
3 - 6
第18步:next()被调用.
第19步:valid()被调用.
第20步:current()被调用.
第21步:key()被调用.
4 - 8
第22步:next()被调用.
第23步:valid()被调用.
...end...
View Code

相关文章:

  • 2022-12-23
  • 2021-05-04
  • 2021-06-25
  • 2022-01-18
  • 2023-03-12
  • 2021-12-03
猜你喜欢
  • 2021-11-17
  • 2021-12-17
  • 2022-12-23
  • 2022-01-12
相关资源
相似解决方案