Reputation: 1168
I'm having problems using generics and lists with interfaces.
I have an interface Comment, which is extended by the class CommentNews.
Comment:
public interface Comment {
public static final String COMMENT_NEWS_PATH = "/comment/news";
public static final String COMMENT_EVENT_PATH = "/comment/event";
public static final String COMMENT_GROUP_PATH = "/comment/group";
public User getUser();
public void setUser(User user);
public String getText();
public void setText(String text);
public Date getModified();
public void setModified(Date modified);
public void setCommentsList(List<?> commentsList);
public <T extends Comment> List<T> getCommentsList();
}
CommentNews:
public class CommentNews implements Comment {
private Integer id;
private User user;
private News news;
private String text;
private List<CommentNews> commentsList;
public CommentNews() {}
// Methods snipped for brevity
public List<CommentNews> getCommentsList() {
return commentsList;
}
public void setCommentsList(List<?> commentsList) {
this.commentsList = (List<CommentNews>) commentsList;
}
}
The problem is with the setCommentsList method, the class cast doesn't actually cast each object in the list. I can't change the methods signature as that will generate a name clash with the interface.
Is there a way to make the casting using generics? I would like to refrain from iterating through the list and casting each object manually.
UPDATE: If I change the Comment interface to If I change the interface to
public <T extends Comment>void setCommentsList(List<T> commentsList);
and CommentNews class to
public void setCommentsList(List<CommentNews> commentsList) {
this.commentsList = commentsList;
}
it should be typesafe, but this results in a name clash between the interface and class.
Upvotes: 0
Views: 901
Reputation: 1500105
Fundamentally, your interface isn't type-safe. There's nothing to stop someone from doing something like this:
Comment comment = ...; // Wherever
List<Integer> numbers = new List<Integer>();
numbers.add(10);
comment.setCommentsList(numbers);
Do you really want to allow that?
You could have a list wrapper which performs the cast whenever it's accessed (rather than up-front) but it would be better to change the interface.
EDIT: If you want any kind of comment to only hold sub-comments of the same kind, you probably want to make your Comment
interface generic, like this:
public interface Comment<T extends Comment<T>> {
// Note: no public modifier; it's allowed by the spec but discouraged
void setCommentList(List<T> comments);
List<T> getCommentList();
}
(You could still use wildcards if you wanted to, but you may well not need to, and it will complicate things.)
Upvotes: 3