Reputation: 3
Without getting bogged down with specifics, my code represents a library whereby each book is made up of a Set of pages containing a Set of Words.
I have created my own Set implementations:
class PageSet<E> extends HashSet<E>(){
public boolean set(int index, E e){....}
....
}
and
class WordSet<E> extends HashSet<E>(){
public boolean set(int index, E e){....}
....
}
I've got stuck when I try to create a Book in my main class:
Set<Set<Word>> dictionary = new PageSet<WordSet<Word>>();
Which results in a type conversion mismatch. However it will quite happily accept
Set<Set<Word>> dictionary = new PageSet<Set<Word>>();
Could someone please shed some light as to what I'm doing wrong when using a generic setup like this?
Upvotes: 0
Views: 70
Reputation: 7899
In any case, you should not extend collections unless you are trying to create new collection types. Since you cannot restrict the visibilities of superclass methods in a subclass, people will be able to write
WordSet<Word> words = ...;
words.clear();
You probably do not want to give clients that power. Instead, use aggregation instead of inheritance.
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<>();
}
Pages in a book are ordered linearly, which is why I used lists. I'm not sure why you used sets. But in any case, by encapsulating the collections inside the classes, you can provide client code exactly the interface you want them to use. The visibilities were chosen deliberately; this looks like a cluster of related classes, but you might want to change them.
Upvotes: 0
Reputation: 27210
It's either
Set<Set<Word>> dictionary = new PageSet<Set<Word>>();
or
Set<WordSet<Word>> dictionary = new PageSet<WordSet<Word>>();
Since although WordSet
is a subclass of Set
, a Set<WordSet>
is not a subclass of Set<Set>
.
In other words, generics are not covariant, which is different from things like arrays.
Upvotes: 1
Reputation: 178333
Basically, a PageSet<WordSet<Word>>
is not a Set<Set<Word>>
, because X<Subclass>
is not a X<Superclass>
.
If you had said
Set<WordSet<Word>> dictionary = new PageSet<WordSet<Word>>();
then that would have worked also.
Upvotes: 3