1

It's probably a simple question but I dont see it.

I have an interface

public interface RenderableListener<T extends Renderable>{
    public void update(T element);
}

I have a super class Renderable and a example class Foo that is extending Renderable.

now, when creating class Foo I give an instance of the interface as listener/ observer or whatever.

Foo foo = new Foo(new RenderableListener<Foo>(){
  public void update(Foo element){}
});

so far everything works and is as it should be.

but now in the Foo class itself when I try to call the interface like this:

public class Foo extends Renderable {
 private final RenderableListener<? extends Renderable> listener;
 public Foo(RenderableListener<? extends Renderable> listener){
  this.listener = listener;
 }
 public void update(){
  listener.update(this);
 }
}

I get this error:

error

Now the issue I have is that SpriteRenderable, the argument in question is extending Renderable. What am I missing?

edit: the idea behind this is that I can use one interface implementation for every class extending Renderable (and there will be plenty).

Adolf
  • 21
  • 3
  • 1
    Please refactor your code (why does a Renderable hold a reference to its own listener?) and show the code for SpriteRenderable. – Silverclaw Jul 25 '16 at 19:58
  • 3
    Read this: http://stackoverflow.com/questions/2723397/what-is-pecs-producer-extends-consumer-super – Arthur Noseda Jul 25 '16 at 19:58
  • @Silverclaw Well it needs to hold the reference. how else could it call the interface? Im not sure I understand what you mean. – Adolf Jul 25 '16 at 20:03
  • 1
    Do you need generics at all? `interface RenderableListener { void update(Renderable renderable); }` is a much more normal and useful thing to want to do. – Sam Jul 25 '16 at 20:39
  • @Sam well that's what Im doing now. But this way I have to cast and with the other method I could have avoided that. – Adolf Jul 25 '16 at 21:25

2 Answers2

0

Your interface species that the update method has a parameter and the update method integrated into your Foo class has no parameters.

In your RenderableListener interface change update(T element) to:

public void update();

That way the method created in Foo matches the specifications presented in RenderableListener.

  • when the Foo#update() is called the listener is called. and the listener has a parameter which extends Renderable. and that is exactly what I dont understand: why can't I pass 'Foo.this' as Parameter, when it clearly extends Renderable. – Adolf Jul 25 '16 at 20:05
  • 1
    @Adolf, it's because `listener` inside `Foo` isn't necessarily a `RenderableListener` - it could be a `RenderableListener` and the compiler can't tell. – Dawood ibn Kareem Jul 25 '16 at 20:07
  • @DavidWallace I see what you mean. The compiler would need to run on good faith that the programmer didnt screw up. I will use a different approach, just not as nice as this one. thanks for the answer. – Adolf Jul 25 '16 at 20:13
-1

Try this:

public class Foo extends Renderable {
    private final RenderableListener<Foo> listener;
    public Foo(RenderableListener<Foo> listener){
        this.listener = listener;
    }
    public void update(){
        listener.update(this);
    }
}
al32
  • 109
  • 3