Marco Vasapollo
Marco Vasapollo

Reputation: 519

Override generic methods through interfaces

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:

How can I obtain the same effect using a different technique?

Upvotes: 2

Views: 324

Answers (1)

cmbaxter
cmbaxter

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

Related Questions