共计 1974 个字符,预计需要花费 5 分钟才能阅读完成。
在 PHP 中,咱们能够非常简单的判断一个变量是什么类型,也能够十分不便的确定一个数组的长度从而决定这个数组是否能够遍历。那么类呢?咱们要如何晓得这个类是否能够通过 foreach 来进行遍历呢?其实,PHP 曾经为咱们提供了一个现成的接口。
class Obj1
{
public $v = 'V:Obj1';
private $prv = 'prv:Obj1';
}
$obj1 = new Obj1();
echo $obj1 instanceof Traversable ? 'yes' : 'no', PHP_EOL; // no
class Obj2 implements IteratorAggregate
{
public $v = 'V:Obj2';
private $prv = 'prv:Obj2';
public function getIterator()
{
return new ArrayIterator([
'v' => $this->v,
'prv' => $this->prv,
]);
}
}
$obj2 = new Obj2();
echo $obj2 instanceof Traversable ? 'yes' : 'no', PHP_EOL; // yes
从下面的例子中能够看出,每一个 \$obj1 无奈通过 Traversable 判断,所以它是不能被遍历的。而第二个 $obj2 则是实现了迭代器接口,这个对象是能够通过 Traversable 判断的。在 PHP 手册中,Traversable 接口正是用于检测一个类是否能够被 foreach 遍历的接口。
这个接口有几个特点:
- 实现此接口的内建类能够应用 foreach 进行遍历而无需实现 IteratorAggregate 或 Iterator 接口。
- 这是一个无奈在 PHP 脚本中实现的外部引擎接口。IteratorAggregate 或 Iterator 接口能够用来代替它。
也就是说这个接口不须要咱们去手工实现,只须要咱们的类实现迭代器相干的接口就能够通过这个接口的验证的判断。如果独自去实现这个接口的话,将会报错并提醒咱们应该去实现 IteratorAggregate 或 Iterator 接口。
// Fatal error: Class ImplTraversable must implement interface Traversable as part of either Iterator or IteratorAggregate in Unknown
class ImplTraversable implements Traversable{}
其实之前的文章中,咱们曾经验证过,对象是能够被遍历的,而且并不需要实现什么迭代器接口就能够被 foreach 遍历。它会输入 所有 public 的属性。
// foreach
foreach ($obj1 as $o1) {echo $o1, PHP_EOL;}
foreach ($obj2 as $o2) {echo $o2, PHP_EOL;}
// V:Obj1
// V:Obj2
// prv:Obj2
也就是说这个 Traversable 接口的作用在理论应用中并不显著。置信咱们决大部分人也并没有应用过这个接口来判断过类是否能够被遍历。然而从下面的例子中咱们能够看出,迭代器可能自定义咱们须要输入的内容。相对来说比间接的对象遍历更加的灵便可控。另外,如果是数组强转对象的状况,Traversable 接口同样无奈进行判断。
$arr = [1, 2, 3, 4];
$obj3 = (object) $arr;
echo $obj3 instanceof Traversable ? 'yes' : 'no', PHP_EOL; // no
foreach ($obj3 as $o3) {echo $o3, PHP_EOL;}
其实,数组自身就是人造的可迭代对象。这里尽管进行了类型强转,但其实应该将数组强转的对象视为默认实现了迭代的器的对象更适合。当然,这类接口更大的意义还是在于代码标准及强制查看方面。
测试代码:
https://github.com/zhangyue0503/dev-blog/blob/master/php/202003/source/%E5%9C%A8PHP%E4%B8%AD%E6%A3%80%E6%B5%8B%E4%B8%80%E4%B8%AA%E7%B1%BB%E6%98%AF%E5%90%A6%E5%8F%AF%E4%BB%A5%E8%A2%ABforeach%E9%81%8D%E5%8E%86.php
参考文档:
https://www.php.net/manual/zh/class.traversable.php
https://www.php.net/manual/zh/control-structures.foreach.php
https://www.php.net/manual/zh/language.oop5.iterations.php
各自媒体平台均可搜寻【硬核项目经理】