27

Between interfaces and enums, which is better for declaring constants? Why is it so?

The Guy with The Hat
  • 10,836
  • 8
  • 57
  • 75
abson
  • 9,148
  • 17
  • 50
  • 69

5 Answers5

19

Its always better to use Enums to declare constants as the objective of interfaces are on a totally different level. Yes, there are lots of interfaces which have a public static final constants, but I feel that enums exclusive job is to provide you these constants.

bragboy
  • 34,892
  • 30
  • 114
  • 171
  • 11
    The `public static final` constants are from a time before `enum`. :) – Bombe Mar 27 '10 at 08:30
  • 6
    @Bombe, that's not entirely true. If, say, `java.lang.Math` was to be rewritten today, `PI` and `E` would still be declared as `public static final double` constants. – gustafc Mar 27 '10 at 09:04
  • 9
    Yes, of course, because last time I checked `Math` was not an interface. – Bombe Mar 27 '10 at 11:52
6

If there is a reason for your constants to have a specific type, if they need some kind of behavior (i.e., methods), or if they are composites of other values, enums are the way to go.

For example, let's assume you're implementing a card game and you want to represent values and suits:

enum Rank { 
    ACE, TWO, THREE, FOUR, FIVE, SIX, SEVEN, 
    EIGHT, NINE, TEN, JACK, QUEEN, KING; 
}
enum Suit { SPADES, CLUBS, DIAMONDS, HEARTS } 

There, it's now impossible to create cards with bogus suits or ranks.

Sometimes, though, you are just interested in having a bunch of frequently used values declared somewhere. In that case, putting them in an enum would just be unnecessary effort, since these constants are just a tool to save us from remembering all the decimals of, say, π when we are calculating the circumference of a circle, or something. Which looks better?

// Using enum:
enum MathConstant { 
    PI(3.14159265358979323846), E(2.7182818284590452354);
    private final double value;
    MathConstant(double v) { value = v; }
    public double value() { return value; } 
}
// Usage:
double circumference = MathConstant.PI.value() * diameter;

// Using a constant class:
final class MathConstants { 
    private MathConstants() { throw new UnsupportedOperationException(); }
    public static final double PI = 3.14159265358979323846,
                               E = 2.7182818284590452354;
}
// Usage:
double circumference = MathConstants.PI * diameter;

As for interfaces: Never put constants in an interface. The "constant interface" pattern is bad (justification), and the only argument to use it has been rendered invalid since import static was added to Java.

Community
  • 1
  • 1
gustafc
  • 28,465
  • 7
  • 73
  • 99
  • Apache's public interface HttpStatus puts constants in an interface, which you advised not to do. Example - int SC_OK = 200; Classes can use these constants by static import of HttpStatus. Is the usage of interface here still a problem ? – MasterJoe Jun 07 '18 at 00:22
  • 2
    Well, sort of. The main reason against interfaces-with-constants is that it makes easy and comfortable to `implement` the interface just to avoid having to import the constants. There are also semantic reasons against it; an interface is a set of behaviours that can be implemented, not a bag of constants. Now, classes aren't really semantically correct places to put constants either, but they can be made final and uninstantiable, which makes them behave more like sub-namespaces rather than classes (which is what we want). – gustafc Jun 11 '18 at 11:06
5

Interfaces are designed to define common behaviours, enums to define common values.

Enum represents a real value which can be compared to another value, or stored in the database easily. You can also have a flag-enum (in C#, don't know in Java) which let you perform binary operations on enum's values (AND, OR, XOR, etc).

twk
  • 3,122
  • 2
  • 26
  • 36
  • 1
    In Java enums are basically (constant) classes, so you can do a lot more with them than with enums in c# prior to .net 4.0. I think C# / .net 4.0 is going to implement this feature. – Tedil Mar 27 '10 at 08:42
  • @Tedil: C# 4.0 feature set's been finalized. It doesn't include the enhanced OO enums. – missingfaktor Mar 27 '10 at 12:02
0

If you work with Java 5 or newer then Enum are the way to go. The only exception is if your list of const is open and can be extended. Enums can not be extended. Another exception is if it are single values like a MAX_INTEGER.

Horcrux7
  • 23,758
  • 21
  • 98
  • 156
0

Just a code :

public interface InterfaceForConstants() {
    String **TOTO** = "Et voilà !";
    double **PI** = 3.14159265358979323846;
}

Using :

class ClasseName implements InterfaceForConstants () {

    String myString;

    if (myString.equals(**TOTO**) {
        // do something
    }

    double circumference = **PI** * diameter; // instead of MathConstants.PI * diameter;

}

Clean and simple. If something can do what you need, take the simplest one! Writing code by the rules is good, writing code that is easy to read is better, even if a rule is not respected. Think about when you have to read your code after a few months. If you want to be more specific, make a javadoc to explain it!

cela
  • 2,352
  • 3
  • 21
  • 43
Arezki
  • 1
  • 3