views:

52

answers:

4

I have a method which needs to take a callback object as an argument and then (at the moment when it's needed) my method will call a specific method of the callback object.

I wrote a class called Manager which has a method called addListener. As the argument for this method I need to use a callback object which is defined by the external software. So, I define the addListener in the following way: public void addListener(Listener listener).

Of course Eclipse complains because it does not know what Listener is (because the Listener is defined by the external software). The only think that I know (should know) about the Listener is that it has a method called doSomething. So, to pleasure Eclipse I add an interface before my Manager class:

interface Listener {
    void doSomething();
}

public class CTManager {
...

The problem seems to be solved but then I try to test my software. So, I create a class called test. In this class I create an instance of the Manager class and try to use addListener method of this instance.

I also create a class Listener, instantiate it and give the instance to the addListener. And it's the place where the problem appears. Eclipse writes that addListener is not applicable to the given argument. I think it's because it expect something from my Listenr interface but gets something from the Listener class.

How can I solve this problem?

+1  A: 

The class Listener that you instanciate must implements the Listener interface you declared to be parameter of the addListener function...

Vinze
But Listener will be provide by an external class (which I do not write). So, I cannot force Listener class to implement my interface. I have no control over the Listener class from the "external" code.
Roman
In any case, your "Listener" parameter and the 3-rd part listener that is actually past in the function must be of the same "type" in order to be accepted by the VM. So either you declare a 3rd part interface as parameter (and you need to add the 3rd part library to your project build path) or you declare you're interface and then 3rd part developer will have to implement it to work in your application...
Vinze
+1  A: 

It looks like the Listener interface that you've created has a different package name to the 3rd-party Listener object that you're trying to accept as an argument.

My preferred solution would be to include the 3rd party library containing the Listener object on your Eclipse Build Path, and then you can actually reference the 3rd-party object directly.

If there's some reason why you can't do this, make sure that your Listener interface is in the same package as the 3rd-party Listener class, so that the fully-qualified names of your interface and the 3rd-party class are identical.

Alison
At the moment I try to model the "3rd party Listener". I do not use any external software at the moment. I have only my code. I create a `test` class in which I import `myGame.Manager` and then try to use `manager.addListener(listener)` where listener is defined in the `Listener` class. It causes the problem because in myGame I have `Listener` interface and I use it to specify type of argument for the `addListener`.
Roman
You may need to fully qualify references to the third-party listener if you also have a local Listener class/interface which is not a placeholder.
Alison
A: 

I think this is probably a build path problem in Eclipse. Check that the JAR file containing the Listener class is on the build path.

Another possibility is that you are missing an import some.package.Listener; statement in the source code of your CTManager class.

Stephen C
+2  A: 

You are on the correct path to a solution. In order to let 2 pieces of software to interface with eachother the 2 pieces need to agree on the contract that is made between them.

A callback mechanism like you describe is quite common. The contract here is the Listener interface which your part uses to call the doSomething() method on the callback object, and which the other part needs to implement in order to offer a valid listener object.

The way Java handles these contacts is by having the classloaders declare that the interface of one part of software is compatible to (or equal to) the interface the other part uses.

This means that both the class or interface names must coincide, but also their packages.

When you built your manager, you also provide an interface definition of the contract, say in:

com.your.program.manager.Listener

This means you will have to give a copy of the file

com/your/program/manager/Listener.java

to the party that buids the callback object, so that they can import the same Listener definition as your manager uses. If both parts use the same definition, the contact will work.

rsp