0

First of all this is not a question about how to implement an interface in Java, or about an error with interfaces. This is a question about the right way to do it, depending on the situation.

First of all i would like to apologize if this is not the correct "stack" to post this question, please let me know and i'll move it to another one.

Let's begin.

What i'm trying to guess is which is the best way to implement an interface in Java. Let's say we have a class A like:

public Class A {

    public A(){}
    public void fooA() {}
}

And an interface

public interface MyListener {
    public void fooListener();
}

Inside fooA() I'm making use of interface B this way:

...
something.setFooListener(/**Doubts here**/)
....

What should we type inside setFooListener(...)

Options are (As far as i know):

A) Define the behavior inside the setFooListener function:

new MyListener.fooListener() {
    /** Implementation of fooListener() **/
}

Pros:

  • Easy and readable as you're reading the function.

  • You can access directly to FINAL variables defined in fooA().

Cons:

  • If your implementation is long enough it would end up in a lack of readability and a too long function.
  • If you're implementing the interface in a few places on the same class you are going to repeat a lot of code.

B) Create an inner class implementing the interface:

private class MyListenerImplementation implements MyListener {
    private String var1;
    private int var2;

    public MyListenerImplementation() {/** constructor **/}

    public void fooListener() {
        /** Do logic here **/
    }
}

Pros:

  • You can keep a reference to the object MyListenerImplementation.
  • You can define variables, functions and everything as it's an object like any other one.
  • Cleaner code.

Cons:

  • Maybe needs more memory.
  • Maybe creating unnecessary classes

C) Hold a variable with a reference to the interface implementation

private MyListener.FooListener myListenerVar = new MyListener.FooListener() {
    /** Logic goes here **/
};

Pros:

  • I actually can't sees anyone comparing to B, but a lot of cons.

Cons:

  • Not a clean code. Doing this on top of your class would be, at least, a war crime.
  • I don't think it's correct to assign a block of code to a variable.
  • I don't like how this looks ;)

D) The last one i could think of; define a function and inside return the implementation

private MyListener.fooListener createMyListener() {
    return new MyListener.fooListener() {
        /** Logic goes here **/
    }
}

Pros:

  • It's cleaner than C.
  • Reusability

Cons:

  • Almost the same ones as C.
  • I don't think it's correct to return a whole block of code.

To sum up: Which i like the most is "B", but i would like to know what does SO thinks of this.

Thanks in advice.

4
  • 4
    I am curious, if you have such detailed list of pros and cons for every option, where exactly are you having a problem deciding which is best for you? I doubt there's an answer that would be right for all cases. Commented Aug 25, 2014 at 13:44
  • 4
    Am I wrong or do I miss something. I think A,C and D won't compile. Or is it just "Pseudo"-Java? Commented Aug 25, 2014 at 13:54
  • @EdwinDalorzo as you said, there are pros and cons on every option, and I'm trying to figure out which one is the best. Solution below says same as you, there's not a single way to do this, it depends on the situation and on what you want to do, code reusability, classes length etc... Commented Aug 25, 2014 at 19:54
  • @Fildor Well actually it's not tested Java code, it should compile but maybe it won't. A) goes inside parenthesis in something.setFooListener(). I believe C and D will compile as it's just a variable and function declaration and syntax is correct, but maybe i'm missing something. Anyway that's not the point of the question. Commented Aug 25, 2014 at 19:56

1 Answer 1

3

Option A is not syntaxically correct. Your pros and cons are valid.

Option B:

  • Maybe needs more memory: no.
  • Maybe creating unnecessary classes: no. Option A also creates a class. It's anonymous, but it's a class, that must be loaded by the ClassLoader like any other class.

Option C: it's exactly the same as A (anonymous class usage), except you initialize a field with the listener. The rule is the same as for any other variable: reduce its scope as much as possible. If you need a field scope, use this option. If you only need the listener in one method, then use a local variable (option A).

Option D: once again, it's the same as A, except you return the created listener instead of only using it.

My recap: you're mixing three orthogonal problems here.

  1. Should I use an anonymous inner class, a named nested class, or a top-level class. This depends on the amount of code contained in the class, and on where you need to use this class: in a single top-level class, or in many top-level classes.
  2. Should I use local variables or instance variables. it's a matter of scope and state, not a matter of interface implementations. Your field or local variable can be initialized with an instance of any kind of your interface implementation
  3. Should you use a factory method returning instances, or should you use new directly. Once again, that has nothing to do with how your interface is implemented. If you want to be loosely coupled, because the factory method might return different implementations of the same interface, use a factory. Otherwise, new is fine.
Sign up to request clarification or add additional context in comments.

2 Comments

Thank you for your answer, and sorry for taking so much to answer you. So, to sum up there is not a more correct way to do this, the chosen option will depend on what we need at the moment. That's actually how i'm facing this problem right now, depending on the situation i'm choosing one or another way to do such things; just wanted to know if there was a "always must use" way to do this. Thank you for your answer once again
You're correct in your approach. Don't be dogmatic and choose the best way depending on the situation.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.