Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/oop/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
PHP SPL RecursiveIterator::getChildren()究竟返回什么?_Php_Oop_Interface_Spl_Recursiveiterator - Fatal编程技术网

PHP SPL RecursiveIterator::getChildren()究竟返回什么?

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

我正在学习Marcus Boerger的标准PHP库(SPL)

我已经实现了自己的递归迭代器,它通过继承实现了
迭代器
接口。它还实现了
可数

我被这些方法弄糊涂了。记录在:

如果

  • current()
    quote:'返回当前元素,并
  • 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 );
            }       
        }
    }