创建一个递归迭代 [英] Creating a recursive iterator
问题描述
我试图写一个迭代器类,它们共同构成了一首歌曲的组件层次。所有的类都是抽象的 MusicComponent
基类的实现,并继承的getChildren()
功能。摘要 MusicTime
子知道实际的音符/和弦玩,和它的所有实现(例如八分音符,四分音符)返回空
为的getChildren()
。
I am trying to write an iterator for a hierarchy of classes that collectively make up the components of a song. All classes are implementations of the abstract MusicComponent
base class and inherit a getChildren()
function. The abstract MusicTime
subclass knows the actual note/chord to play, and all its implementations (e.g. quaver, crotchet) return null
for getChildren()
.
其它部件 MusicComponent
持有 MusicTimes
的集合,例如酒吧的时间,而科
持有的 MusicComponents
。 歌曲
持有部分
组成的歌曲如:诗句,合唱团,用不同的节奏节/时的签名。
The other components are MusicComponent
which holds a collection of MusicTimes
e.g. a bar at a time, and Section
which holds the MusicComponents
. Song
holds the Sections
that make up the song e.g. verses, choruses, sections with different tempos/time signatures.
我需要的是一个迭代,将遍历所有部分
在歌曲
,那么所有的 MusicComponents
在科
,只有当它找到一个 MusicTime
传人,戏剧音符的时间是根据它的音符类型的长度,其含有部分的拍号和速度
。
What I need is an iterator that will iterate through all Sections
in a Song
, then all MusicComponents
in the Section
and only when it finds a MusicTime
descendant, play the note for the length of time based on its note type, and the time signature and tempo of its containing Section
.
抱歉,如果太多的信息,但只有这样,我可以解释我想要做的。所以,我需要处理这一堆,记录其中 MusicComponents
我visted或者是有没有办法这个只是用递归做?
Sorry if too much info, but was the only way I could explain what I'm trying to do. So do I need to handle this with a stack, recording which MusicComponents
I've visted or is there a way to do this just using recursion?
推荐答案
您可以写一个迭代器会连接其子的迭代器,甚至懒洋洋地。呼叫下一个()
在歌曲
的迭代器,然后将深入挖掘科
和 MusicComponent
迭代器和最终实现下一个 MusicTime
。
You can write an iterator which "concatenates" the iterators of its children, even lazily. Calling next()
on a Song
's iterator would then drill down through the Section
and MusicComponent
iterators and finally deliver the next MusicTime
.
番石榴使这个容易。让 MusicComponent
的可迭代< MusicTime>
和实施迭代器()
为:
Guava makes this easy. Make MusicComponent
an Iterable<MusicTime>
and implement iterator()
as:
@Override
public Iterator<MusicTime> iterator() {
return Iterables.concat(getChildren()).iterator();
}
由于所有的孩子都 MusicComponent
和由此实施可迭代&LT; MusicTime&GT;
自己,宋
的迭代器将部分的串联
迭代器,这本身就是 MusicTime
迭代器。
Since all children are MusicComponent
s and thus implement Iterable<MusicTime>
themselves, Song
's iterator will be a concatenation of Section
iterators, which are themselves concatenations of MusicTime
iterators.
这最后的迭代器是一种特殊情况。 A MusicTime
迭代器只能返回自己一次:
This last iterator is a special case. A MusicTime
iterator should only return itself once:
@Override
public Iterator<MusicTime> iterator() {
return Iterators.singletonIterator(this);
}
另外,科
的迭代器可以改为:
Alternatively, Section
's iterator could be replaced with:
@Override
public Iterator<MusicTime> iterator() {
return getChildren().iterator();
}
通过这一点,迭代变得那么容易,因为:
With this, iterating becomes as easy as:
for (MusicTime time : song) {
player.play(time);
}
您现在可以做任何类型的操作(播放,计算总工期,...)无需重新执行递归。
You can now do any kind of operation (playing, counting the total duration,...) without re-implementing the recursion.
有您的问题的替代解决方案,虽然,但是这一切都归结到设计选择。例如,你可以有一个播放
在 MusicComponent
其中歌曲$ C $方法C>和
科
通过调用将实施播放
所有子女。这是一个简单的递归实现,但你必须为你要添加的 MusicComponent
(如所有行动中发挥重复递归
, getTotalDuration
,...)。
There are alternative solutions for your problem though, but it all comes down to design choices. For example, you could have a play
method on MusicComponent
which Song
and Section
would implement by calling play
on all of their children. This is a straightforward recursive implementation, but you must repeat the recursion for all operations you intend to add on MusicComponent
(such as play
, getTotalDuration
, ...).
如果您需要更多的灵活性,您可以使用 Visitor设计模式并让您的播放操作访客(如 PlayVisitor
)。这样做的好处是,你可以决定控制从游客中的迭代顺序,但使得它很难增加新的 MusicComponent
的实施。
If you need more flexibility, you could use the Visitor design pattern and make your play operation a visitor (e.g. PlayVisitor
). This has the advantage that you can decide to control the iteration order from within the visitor, but makes it harder to add new MusicComponent
implementations.
这篇关于创建一个递归迭代的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!