首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >::getChildren()返回什么?

::getChildren()返回什么?
EN

Stack Overflow用户
提问于 2013-07-03 03:53:39
回答 1查看 417关注 0票数 1

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

我实现了自己的RecursiveIterator,通过继承实现了Iterator接口。它还实现了Countable

我对电流()getChildren()hasChildren方法感到困惑。记录在:http://www.php.net/~helly/php/ext/spl/interfaceRecursiveIterator.html上。

如果

  • current()引号:‘返回当前元素’,以及
  • getChildren()返回‘当前元素的子迭代器’,我引用这句话

如果像current()一样,当前元素是指当前对象的子元素。

然后,文档肯定是在指定getChildren(),实际上是返回所述节点的getChildren()。

所以很困惑。

代码语言:javascript
复制
<?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()返回一个实现RecursiveIterator和Countable的对象。因为每个RecursableCountableIterableNode对象都包含其他RecursableCountableIterableNode对象的实例。我认为这是一种复合模式。

通过实验,我成功地在树上执行了递归操作,方法是使用count() (作为退出递归进程的终端条件)和foreach来迭代每个节点的子节点。

有趣的是,实际上,count特性隐式执行hasChildren操作,foreach构造隐式执行getChildren操作以执行递归遍历。

代码语言:javascript
复制
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 );
            }       
        }
    }

有鉴于此,我认为为了成为一个实用的RecursiveIterator,

  • getChildren确实应该返回$this而不是current()的节点,并且
  • hasChildren确实应该返回count($this)的布尔转换结果

是这样吗?

说明书上说了一件事--我从字面上看。但我的实际经验是另一种说法。

EN

回答 1

Stack Overflow用户

发布于 2013-07-06 15:58:00

我觉得说“孙子”是不对的。您只是将参考点从当前迭代器的一个元素更改为当前迭代器,这使子元素变为大子元素。我看不出有什么好的理由这么做,因为这不是我习惯使用spl迭代器的惯例。

我建议您像发布的代码一样坚持使用代码,但我认为您可能不知道RecursiveIteratorIterator。RecursiveIteratorIterator意味着它将处理调用hasChildren()和getChildren()的复杂性,并在过程中维护适当的迭代器堆栈。最后,您将得到一个看似扁平的层次结构列表。您的NodeTreeProcessor类目前正在做一些此类工作。然后,您只需预先处理RecursiveIteratorIterator,然后根据您使用的标志首先获得宽度或深度第一次迭代。不过,您不必使用RecursiveIteratorIterator。

此外,考虑在调用getChildren()时返回一个新的外部迭代器。否则,您将放弃每次使用多个迭代器在同一个节点上迭代的可能性,因为迭代器的位置将是共享状态。目前,您使用的是内部迭代器范例,其中数据和迭代状态都存储在同一个对象中。外部迭代器将迭代状态从数据中分离出来,允许在同一数据块上有多个活动迭代器。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/17439375

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档