art*_*olk 4 php iterator design-patterns
请给VolkerK检查答案,他提供了另一种解决方案,但我不能将两个帖子标记为答案.:(
美好的一天!
我知道C#允许使用yield的多个迭代器,如下所述: c#中是否可以使用多个迭代器?
在PHP中有和Iterator接口.是否可以为类实现多个迭代方案?
更多细节(编辑):
例如,我有类TreeNode实现单树节点.整个树只能使用一个这个类来表示.我想提供迭代器来迭代当前节点的所有直接和间接子节点,例如使用BreadthFirst或DepthFirst顺序.
我可以将这个Iterators实现为单独的类,但这样做我需要树节点将它的子集合公开为public.
C#伪代码:
public class TreeNode<T>
{
...
public IEnumerable<T> DepthFirstEnumerator
{
get
{
// Some tree traversal using 'yield return'
}
}
public IEnumerable<T> BreadthFirstEnumerator
{
get
{
// Some tree traversal using 'yield return'
}
}
}
Run Code Online (Sandbox Code Playgroud)
是的你可以.
foreach(new IteratorOne($obj) as $foo) ....
foreach(new IteratorTwo($obj) as $bar) .....
Run Code Online (Sandbox Code Playgroud)
实际上,只要您的类实现了Iterator,就可以将任意IteratorIterator应用于它.这是一件好事,因为应用元迭代器不需要知道有关该类的任何信息.
例如,考虑一个像这样的可迭代类
class JustList implements Iterator
{
function __construct() { $this->items = func_get_args(); }
function rewind() { return reset($this->items); }
function current() { return current($this->items); }
function key() { return key($this->items); }
function next() { return next($this->items); }
function valid() { return key($this->items) !== null; }
}
Run Code Online (Sandbox Code Playgroud)
让我们定义一些元迭代器
class OddIterator extends FilterIterator {
function accept() { return parent::current() % 2; }
}
class EvenIterator extends FilterIterator {
function accept() { return parent::current() % 2 == 0; }
}
Run Code Online (Sandbox Code Playgroud)
现在将元迭代器应用于基类:
$list = new JustList(1, 2, 3, 4, 5, 6, 7, 8, 9);
foreach(new OddIterator($list) as $p) echo $p; // prints 13579
foreach(new EvenIterator($list) as $p) echo $p; // prints 2468
Run Code Online (Sandbox Code Playgroud)
更新:php没有内部类,所以你在这里运气不好,至少没有求助于eval.您的迭代器需要是单独的类,它们知道基类结构.通过在基类中提供实例化后台迭代器的方法,可以降低其危害:
class TreeDepthFirstIterator implements Iterator
{
function __construct($someTree).....
}
class Tree
{
function depthFirst() { return new TreeDepthFirstIterator($this); }
....
}
foreach($myTree->depthFirst() as $node).....
Run Code Online (Sandbox Code Playgroud)
另一种选择是使用lambdas而不是foreach.这更好,更灵活,但需要php5.3:
class Tree
{
function depthFirst($func) {
while($node = .....)
$func($node);
.....
$myTree->depthFirst(function($node) {
echo $node->name;
});
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
1217 次 |
| 最近记录: |