PHP SPL RecursiveIterator::getChildren()究竟返回什么?
我正在学习Marcus Boerger的标准PHP库(SPL) 我已经实现了自己的递归迭代器,它通过继承实现了PHP SPL RecursiveIterator::getChildren()究竟返回什么?,php,oop,interface,spl,recursiveiterator,Php,Oop,Interface,Spl,Recursiveiterator,我正在学习Marcus Boerger的标准PHP库(SPL) 我已经实现了自己的递归迭代器,它通过继承实现了迭代器接口。它还实现了可数 我被这些方法弄糊涂了。记录在: 如果 current()quote:'返回当前元素,并 getChildren()返回当前元素的子迭代器 如果与current()的情况一样,当前元素表示当前对象的子对象 然后,文档肯定指定getChildren()实际上返回所讨论节点的孙辈 因此感到困惑 <?php /** *@desc Represents a
迭代器
接口。它还实现了可数
我被这些方法弄糊涂了。记录在:
如果
quote:'返回当前元素,并current()
返回当前元素的子迭代器getChildren()
current()
的情况一样,当前元素表示当前对象的子对象
然后,文档肯定指定getChildren()实际上返回所讨论节点的孙辈
因此感到困惑
<?php
/**
*@desc Represents a node within a hierarchy
*/
class RecursableCountableIterableNode implements RecursiveIterator, Countable
{
public $title;
private $_componentsArray;
private $_iteratorPosition;
/**
*@desc adds component
*/
public function addComponent(
RecursableCountableIterableNode $incomingNodeObj
)
{
foreach ( $this->_componentsArray as $componentNodeObj )
{
if ( $incomingNodeObj === $componentNodeObj )
{
//its is already in there
return;
}
}
//add to the next element of the numerically indexed array
$this->_componentsArray[] = $incomingNodeObj;
}
/**
* @desc RecursiveIterator Interface
*/
/**
* @desc Implements the RecursiveIterator Interface
* @return boolean - Whether or not the node at the current element
* has children.
*
* Note: This method does NOT count the children of this node,
* it counts the components of the node at the *current* element.
* There is a subtle but important difference.
* It could have been better to name
* the interface method 'hasGrandChildren()'.
*/
public function hasChildren()
{
return ( boolean ) count( $this->current() );
}
/**
* @desc Gets the node of the current element which in effect is a container
* for childnodes.
*
* Note: According to the SPL, it does NOT get 'the child elements of
* the current node' ($this->_componentsArray) which was a surprise to me.
*
* @return RecursableCountableIterableNode - the
* sub iterator for the current element
*
*/
public function getChildren()
{
return $this->current();
}
/**
* @desc To adhere to countable interface.
* @returns integer - The number of elements in the compondents array.
*/
public function count()
{
return count( $this->_componentsArray );
}
/**
* Iterator methods
*/
/**
* @desc Rewind the iterator to the first element.
* @return void
*/
public function rewind()
{
$this->_iteratorPosition = 0;
}
/**
* @desc Return the current element.
* @return RecursableCountableIterableNode
*/
public function current()
{
return $this->_componentsArray[ $this->_iteratorPosition ];
}
/**
* @desc Return the key of the current element.
* @return integer
*/
public function key()
{
return $this->_iteratorPosition;
}
/**
* @desc Move forward to the next element.
* @return void
*/
public function next()
{
++$this->_iteratorPosition;
}
/**
* @desc Checks if current position has an element
* @return boolean
*/
public function valid()
{
return isset( $this->_componentsArray[ $this->_iteratorPosition ] );
}
}
鉴于此,我认为为了成为一个实用的递归迭代器
确实应该返回getChildren
而不是$this
处的节点,并且current()
确实应该返回haschilds
count($this)
规格说明了一件事——我从字面上理解。但我的实践经验说明了另一个问题。我认为说“孙子女”是不对的。您只需将引用点从当前迭代器的a元素更改为当前迭代器,这会使子元素变成大元素。我看不出这样做的理由,因为这不是我习惯于使用spl迭代器的惯例 我建议你坚持你发布的代码,但我想你可能不知道。RecursiveIteratorIterator可以处理调用hasChildren()和getChildren()的复杂性,并在过程中维护一个适当的迭代器堆栈。最后,你会看到一个层次结构的扁平列表。您的NodeReeprocessor类当前正在执行其中一些操作。然后,您可以在递归迭代器上进行foreach,根据您使用的标志,您将得到广度优先或深度优先的迭代。不过,您不必使用递归迭代器
也可以考虑调用GeEngEnter()时返回一个新的外部迭代器。否则,您将放弃一次使用多个迭代器在同一节点上迭代的可能性,因为迭代器的位置将是共享状态。目前,您使用的是内部迭代器范例,其中数据和迭代状态都存储在同一个对象中。外部迭代器将迭代状态与数据分离,使同一数据段上有多个活动迭代器。
我认为说“大孩子”是不对的。您只需将引用点从当前迭代器的a元素更改为当前迭代器,这会使子元素变成大元素。我看不出这样做的理由,因为这不是我习惯于使用spl迭代器的惯例 我建议你坚持你发布的代码,但我想你可能不知道。RecursiveIteratorIterator可以处理调用hasChildren()和getChildren()的复杂性,并在过程中维护一个适当的迭代器堆栈。最后,你会看到一个层次结构的扁平列表。您的NodeReeprocessor类当前正在执行其中一些操作。然后,您可以在递归迭代器上进行foreach,根据您使用的标志,您将得到广度优先或深度优先的迭代。不过,您不必使用递归迭代器也可以考虑调用GeEngEnter()时返回一个新的外部迭代器。否则,您将放弃一次使用多个迭代器在同一节点上迭代的可能性,因为迭代器的位置将是共享状态。目前,您使用的是内部迭代器范例,其中数据和迭代状态都存储在同一个对象中。外部迭代器将迭代状态与数据分离,使同一数据段上有多个活动迭代器。
getChildren应返回另一个迭代器中包装的current()。如果有孩子,谢谢你的评论。它确实返回current()-但没有像您所说的那样进行包装。我应该澄清一下,getChildren()
确实返回了一个实现递归迭代器和可数的对象。每个RecursableCountableIterableNode
对象都包含其他RecursableCountableIterableNode
对象的实例。我认为这是一种复合模式。我将编辑这个问题以澄清。@t关于我上面的评论,有什么理由应该用另一个迭代器包装它吗?这样你就可以用真正的“递归”方式对它们进行迭代GetChildren应该返回另一个迭代器包装的current()。如果有孩子,谢谢你的评论。它确实返回current()-但没有像您所说的那样进行包装。我应该澄清一下,getChildren()
确实返回了一个实现递归迭代器和可数的对象。每个RecursableCountableIterableNode
对象都包含其他RecursableCountableIterableNode
对象的实例。我认为这是一种复合模式。我将对问题进行编辑以澄清。@t关于我上面的评论,有什么理由将其包装在另一个迭代器中吗?这样您就可以以真正的“递归”方式对其进行迭代谢谢您的回答。非常有用的信息。谢谢你的回答。非常有用的信息。
class NodeTreeProcessor
{
protected $output = '';
public function doProcessingWithNode(
RecursableCountableIterableNode $treeNodeObj
)
{
$this->output .= $treeNodeObj->title;
//Base case that stops the recursion.
if (!( count( $treeNodeObj ) > 0 ))
{
//it has no children
return;
}
//Recursive case.
foreach( $treeNodeObj as $childNode )
{
$this->doProcessingWithNode( $childNode );
}
}
}