Reputation: 519
I have some contents, generated by this interface:
public interface Content {
void addListener(ContentListener<?> listener);
}
Like GenericContent
:
public interface GenericContent extends Content {
@Override
void addListener(GenericContentListener listener);
}
These are ContentListener
and GenericContentListener
public interface ContentListener<T extends Content> {
void ping(T content);
}
public interface GenericContentListener extends ContentListener<GenericContent>
{
}
My problem is that the method addListener
into GenericContent
is a double error:
The method addListener(ContentListener<GenericContent>)
of type GenericContent
must override or implement a supertype method
Name clash: The method addListener(ContentListener<GenericContent>)
of type GenericContent
has the same erasure as addListener(ContentListener<?>)
of type Content
but does not override it
How can I obtain the same effect using a different technique?
Upvotes: 2
Views: 324
Reputation: 35463
Try removing the @Override
annotation. Typically, you use @Override
in a class and not an interface, using it to tell you that this method must override another, and if it ever fails to (like if the super class method signature changes), a compilation error is thrown. Doing that made things compile for me. I also made one tweak to the structure:
public interface Content {
void addListener(ContentListener<? extends Content> listener);
}
public interface GenericContent extends Content {
void addListener(GenericContentListener listener);
}
public interface ContentListener<T extends Content> {
void ping(T content);
}
public interface GenericContentListener extends ContentListener<GenericContent>
{
}
Now in addition to that, you might want to consider redefining Content
and then GenericContent
like this:
public interface Content<T extends Content> {
void addListener(ContentListener<T> listener);
}
public interface GenericContent extends Content<GenericContent> {
void addListener(GenericContentListener listener);
}
As it stands, your Content
interface will allow a ContentListener
of any type of Content
to be added. This change enforces that the ContentListener
added must be for the type of Content
that this is.
Then, you could probably take it a step further and do this:
public interface Content<T extends Content, L extends ContentListener<T>> {
void addListener(L listener);
}
public interface GenericContent extends Content<GenericContent, GenericContentListener> {
}
Now when someone implements GenericContent
, it is assumed that the addListener
method signature will be:
void addListener(GenericContentListener listener);
Upvotes: 2