我有各种类来定义一段音乐的结构元素。层次结构为Song
> Section
> CompositeMusic
> MusicTime
,所有这些都继承自抽象的MusicComponent
类。
MusicTime
是底层,知道要播放哪个Chord
以及有多少个四分音符,并且包含在CompositeMusic
个对象的小节中。 Section
依次保留CompositeMusics
并允许进行速度和时间签名更改。
我需要能够递归遍历Sections
中的所有Song
,每个CompositeMusics
中的所有Section
,并在每个MusicTimes
中播放所有CompositeMusic
MusicTime
。换句话说,遍历每种类型的所有子项,除非它是List<MusicComponent> getChildren()
,在这种情况下播放它。
我天真地以为我能够在MusicComponent
基类上放置一个抽象的List<Section>
,所以我可以用同样的方式迭代任何后代。但是这是不允许的,因为例如它不会接受public abstract class MusicComponent {
public MusicComponent() {
}
public abstract void play();
public abstract boolean addComponent(MusicComponent component);
public abstract List<MusicComponent> getChildren();
}
。
所以我的问题是,递归迭代来自同一基类的不同对象的正确方法是什么?
修改
根据要求提供代码示例:
基类
public class Song extends MusicComponent {
String songName;
List<Section> sections;
public Song(String songName, List<Section> sections) {
this.songName = songName;
this.sections = sections;
}
子类的示例
Song
这就是我要对Section
做的事情(以及CompositeMusic
和@Override
public List<MusicComponent> getChildren() {
return sections;
}
的等效内容)
List<Section>
但它抛出了一个编译错误,因为它无法从List<MusicComponent>
隐式转换为Section
,即使MusicComponent
来自{{1}},这就是我所说的希望能够做到
答案 0 :(得分:3)
尝试使用List<? extends MusicComponent>
作为返回类型
答案 1 :(得分:0)
从Java 1.5开始支持协变返回类型,因此如果基类方法被覆盖,getChildren()方法基本上可以返回MusicComponent子类的任何列表。您需要做的是在使用instanceof进行迭代检查之前,确保要迭代的列表变量的类型正确。
答案 2 :(得分:0)
请参阅维基百科中的访客设计模式。这是递归迭代复杂层次结构的经典方法。 设计模式是简单用例的开销,但如果您的模型将来会发展,它会有所帮助。