0

我很难去RecursiveFilterIterator拜访我不想接受的对象的孩子,而不返回不可接受的对象。

我有两种类型的Node对象:NodeTypeA并且NodeTypeA,它们都扩展了抽象类型Node

abstract class Node implements Countable, RecursiveIterator
{
    protected $children;

    public function __construct( array $children = array() )
    {
        $this->children = $children;
    }

    public function count()
    {
        return count( $this->children );
    }

    public function hasChildren()
    {
        if( !$this->valid() )
        {
            return false;
        }

        return count( $this->current() ) > 0;
    }

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

    public function rewind()
    {
        reset( $this->children );
    }

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

    public function valid()
    {
        return null !== $this->key();
    }

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

    public function next()
    {
        next( $this->children );
    }
}

class NodeTypeA extends Node {}

class NodeTypeB extends Node {}

...我为此定义了这个RecursiveFilterIterator

class RecursiveNodeFilterIterator
    extends RecursiveFilterIterator
{
    public function __construct( RecursiveIterator $iterator, $kind )
    {
        parent::__construct( $iterator );

        $this->kind = $kind;
    }

    public function accept()
    {
        $current = $this->current();
        return $this->hasChildren() || $current instanceof $this->kind;
    }

    public function getChildren()
    {
        return new self( $this->getInnerIterator()->getChildren(), $this->kind );
    }
}

然后,当我运行此代码段时:

header( 'Content-Type: text/plain; charset=utf-8' );

$nodes = new NodeTypeA( array(
    new NodeTypeB( array(
        new NodeTypeA( array(
            new NodeTypeB( array(
                new NodeTypeA(),
                new NodeTypeA()
            ) ),
        ) ),
        new NodeTypeA( array(
            new NodeTypeB( array(
                new NodeTypeB( array(
                    new NodeTypeA(),
                    new NodeTypeB()
                ) ),
            ) )
        ) ),
        new NodeTypeB()
    ) ),
    new NodeTypeA()
) );

$rii = new RecursiveIteratorIterator(
    new RecursiveNodeFilterIterator( $nodes, 'NodeTypeA' ),
    RecursiveIteratorIterator::SELF_FIRST
);

foreach( $rii as $node )
{
   echo str_repeat( '  ', $rii->getDepth() ) . get_class( $node ) . PHP_EOL;
}

我希望得到这个结果:

  NodeTypeA
      NodeTypeA
      NodeTypeA
  NodeTypeA
        NodeTypeA
NodeTypeA

...但得到:

NodeTypeB
  NodeTypeA
    NodeTypeB
      NodeTypeA
      NodeTypeA
  NodeTypeA
    NodeTypeB
      NodeTypeB
        NodeTypeA
NodeTypeA

换句话说,在迭代时,它也会NodeTypeB在有子对象时返回对象。这是有道理的,因为在RecursiveNodeFilterIterator::accept()我已经定义return $this->hasChildren() || ...了 ,以便过滤器访问所有可能的子节点。

有没有办法RecursiveNodeFilterIterator访问子节点NodeTypeB而不实际返回NodeTypeB节点本身?

4

1 回答 1

2

RecursiveIteratorIterator一个简单的选择是用过滤器迭代器包装accepts,它只包含您感兴趣的项目。

(从评论移到答案)

于 2013-12-16T09:41:08.783 回答