5

I am aware that putting constants in an interface is generally considered bad practice but...

I am using the Observer pattern to broadcast events from an object to a listener.

interface DownloadListener 
{
    public void sendEvent(int eventId);
}

The broadcaster uses constant ints to tell the listener which event has happened.

class DownloadTask 
{
    public static final int EVENT_DOWNLOAD_STARTED = 1;
    public static final int EVENT_DOWNLOAD_COMPLETED = 2; //should these go here?

    DownloadTask(DownloadListener listener)
    {
        listener.sendEvent(EVENT_DOWNLOAD_STARTED);
    }
}

Would it be better to place the constants inside the interface? My thinking is that the interface is the contract between the broadcaster and the listener and therefore it should contain the details (constants) of that contract.

I'm developing for mobile (Java 1.3) so unfortunately can't use an enum type.

Michael Borgwardt
  • 342,105
  • 78
  • 482
  • 720
donturner
  • 17,867
  • 8
  • 59
  • 81

7 Answers7

11

Interfaces describe services, so if the constant is part of the description or definition of the service it should go in the interface, so every implementation of that interface can reuse them. In your case for example constants should go to the interface

Jaime Hablutzel
  • 6,117
  • 5
  • 40
  • 57
4

The interface seems like an acceptable place for them.

I think your "putting constants in an interface is generally considered bad practice" statement really only applies if you're using the Constant Interface anti-pattern.

Community
  • 1
  • 1
Rob Hruska
  • 118,520
  • 32
  • 167
  • 192
2

Extending Voo's answer

interface DownloadListener 
{
    public void sendEvent(MyEnum eventId);

    public class MyEnum
    {
        private final static MyEnum ENUM_1 = new MyEnum();
        private final static MyEnum ENUM_2 = new MyEnum();

        private MyEnum()
        {
        }
    }

    public static final MyEnum EVENT_DOWNLOAD_STARTED = MyEnum . ENUM_1;
    public static final MyEnum EVENT_DOWNLOAD_COMPLETED = MyEnum . ENUM_2 ;
}
Community
  • 1
  • 1
emory
  • 10,725
  • 2
  • 30
  • 58
2

Remember to steer clear from the constants interface anti-pattern: http://en.wikipedia.org/wiki/Constant_interface

Wivani
  • 2,036
  • 22
  • 28
1

That's fine, but I'd really replace the int with a handrolled enum, something like:

public class MyEnum {
    public final static MyEnum ENUM_1 = new MyEnum();
    public final static MyEnum ENUM_2 = new MyEnum();

    private MyEnum() {
    }
}

easy to extend if you need additional information sometime (debugging is simpler if you have a String property and overwrite to String compared to an int..) and it's type safe.

Has the downside that you can't declare it in the interface definition itself, but you can use the enum in the interface method definitions which should be good enough.

Voo
  • 29,040
  • 11
  • 82
  • 156
  • 1
    Good answer, but why can't you declare it in the interface definition itself. It seemed to work for me - http://stackoverflow.com/a/8424867/348975. – emory Dec 08 '11 at 01:01
  • 3
    @emory I.. I'm.. what? Why the hell can you define a public class inside an interface? That.. I'm speechless, wow I've written in Java for years now and there I thought I actually knew the language :( So the only reason really was my ignorance, your solution is much better really. – Voo Dec 08 '11 at 01:12
0

It seems like there has to be a better way.

interface DownloadListener 
{
    public void downloadStarted ( ) ;

    public void downloadCompleted ( ) ;
}
emory
  • 10,725
  • 2
  • 30
  • 58
0

Historically constants are placed into interfaces because the interface seldom change out more often then the implementing concrete classes.

Also, when an interface is being implemented by many classes and used by them, it makes sense to place it in the interface to remove the dependency.

With Java 5 and above I believe you should be looking at enum data structure for such purpose, and note that enum cannot be placed in an interface. It can be placed in a class, or by its own.

Oh Chin Boon
  • 23,028
  • 51
  • 143
  • 215
  • Why can't the enum be placed in an interface? http://docs.oracle.com/javase/6/docs/jdk/api/javac/tree/com/sun/source/tree/Tree.Kind.html is a counterexample. – emory Dec 08 '11 at 01:09
  • Do you mean that you can compose a Java enum in an interface? – Oh Chin Boon Dec 08 '11 at 01:26