简体   繁体   中英

Extending an Interface vs Instantiating via Anonymous Class

NOTE: I am aware that this is dangerously close to many other questions. I haven't seen any, however, that do not pertain specifically to Android's OnClickListener interface. I am asking in a general sense.

I understand the difference between instantiating an interface via an anonymous class... a la:

private final Runnable runnable = new Runnable() {
    @Override
    public void run() {
        draw();
    }

};

... and extending the interface.

public class ClassyClass implements Runnable {
    ...
    //do other cool stuff here
    ...
    @Override
    public void run() {
        draw();
    }
    ...
    //and more here
    ...

}

But, other than the obvious benefits from interfaces such as OnClickListener is there a strong advantage to either option?

I would think that extending it would be the obvious choice because you are already creating that object - no duplication of effort. Is this right?

I am asking in a general sense but, as I am currently working with Runnable , if it has sees an advantage from either option I'd love to know.

Well here is an example that shows the main differences. It's a little contrived but it's just to illustrate.

Here is an anonymous version:

class PrintBuilder {
    List<Runnable> printers = new LinkedList<>();

    List<Runnable> get() {
        return printers;
    }

    PrintBuilder add(final String line) {
        printers.add(new Runnable() {
            public void run() {
                System.out.println(line);
            }
        });

        return this;
    }
}

Here is a nested version:

class PrintBuilder {
    List<Printer> printers = new LinkedList<>();

    PrintBuilder add(String line) {
        printers.add(new Printer(line));
        return this;
    }

    List<Printer> get() {
        return printers;
    }

    static class Printer implements Runnable {
        String line;

        Printer(String line) {
            this.line = line;
        }

        public void run() {
            System.out.println(line);
        }
    }
}

So you can see the main differences are then:

  • An anonymous class is inner and it has an implicit reference to the enclosing instance.

In particular, in the above example, the PrintBuilder is leaked until the inner Runnable objects die. In the second example, the Runnable class is static so it doesn't have this problem.

  • Anonymous classes are a little bit shorter.

An anonymous class doesn't need fields and constructors because they are implicit.

  • Big difference in the way the code is organized.

An anonymous class is declared where it's instantiated and this can be pretty destructive to the layout of the enclosing class if the anonymous class isn't very short. On the other hand if the anonymous class is short, the functional-like syntax is nice.

Also all classes tend to grow and in my experience this can turn in to a smell when an anonymous class gets too big. Anonymous classes are also much more difficult to refactor in to a top-level class.

The first snippet defines a class, without a name, that implements the Runnable interface (and instantiates that anonymous class). The second one defines a class, with a name, that also implements the Runnable interface.

There's no difference in terms of inheritance and interface implementation except the second class has a name and the first one doesn't.

The second snippet allows multiple classes to instantiate the Runnable implementation, whereas the first one defines a class that is only known from its enclosing class. Sometimes one is better, sometimes the other.

Both approaches are valid. Which one to use depends of your usage:

  • If you implement an interface inside another class, you will have access to protected and private methods of the parent class.
  • If you want to keep things separated and reuse the same implementation for this interface, creating a separate class is the way to go.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM