繁体   English   中英

嵌套的通用集合

[英]Nested generic collections

不用担心细节,我的代码代表了一个图书馆,每本书由一组页面和一组单词组成。

我创建了自己的Set实现:

class PageSet<E> extends HashSet<E>(){
    public boolean set(int index, E e){....}
    ....
}

class WordSet<E> extends HashSet<E>(){
    public boolean set(int index, E e){....}
    ....
}

当我尝试在主班级创建一本书时,我陷入了困境:

Set<Set<Word>> dictionary = new PageSet<WordSet<Word>>();

导致类型转换不匹配。 但是它会很高兴地接受

Set<Set<Word>> dictionary = new PageSet<Set<Word>>();

使用这种通用设置时,有人可以说明我做错了什么吗?

基本上, PageSet<WordSet<Word>>不是Set<Set<Word>> ,因为X<Subclass>不是X<Superclass>

如果你说过

Set<WordSet<Word>> dictionary = new PageSet<WordSet<Word>>();

那么那也行得通。

要么

Set<Set<Word>> dictionary = new PageSet<Set<Word>>();

要么

Set<WordSet<Word>> dictionary = new PageSet<WordSet<Word>>();

由于尽管WordSetSet的子类,所以Set<WordSet>不是Set<Set>的子类。

换句话说,泛型不是协变的 ,这与数组之类的东西不同。

无论如何,除非您试图创建新的集合类型,否则不应该扩展集合。 由于您不能限制子类中超类方法的可见性,因此人们可以编写

WordSet<Word> words = ...;
words.clear();

您可能不想赋予客户这种权力。 而是使用聚合而不是继承。

class Word {
    private String text;
    private PartOfSpeech part;
    // Constructors, getters, setters, equals, hashCode are elided.
}

class Page {
    private int pageNumber;
    private Set<Word> contents = new HashSet<>();

public class Book {
    private String title;
    private List<Page> pages = new ArrayList<>();
}

一本书中的页面是线性排列的,这就是我使用列表的原因。 我不确定为什么要使用布景。 但是无论如何,通过将集合封装在类中,可以为客户端代码提供您希望它们使用的确切接口。 可见性是故意选择的; 这看起来像一堆相关的类,但是您可能想要更改它们。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM