Thomas G. Marshall said:
Dale King <
[email protected]> coughed up the following:
...[Thwack]...
I get really disgusted when someone says that this "contradicts the
basic purpose of an interface" to use it only to define constants.
How does your class version not contradict the basic purpose of a
class?
I'm sorry that you get disgusted over this. The point of the class is that
you access the statics in a qualified way. You correctly point out that
subclassing the class allows unqualified access below, which I try to answer
below.
Let me try to restate this. I can understand your objections on a stylistic
basis. Implementing an interface to access constants unqualified is usually
a bad practice and I'm glad that in 1.5 we can just do static import to use
constants unqualifed. And I have no trouble with anyone saying that you
should refrain from doing it that way. But sometimes having to qualify every
single access to every constant can lead to less readable code and requires
more laborious typing.
My problem is when someone tries to dress the argument up and say this
violates the purpose of an interface. And you aren't the only one to do so.
In reality it doesn't contradict the "basic purpose" of an interface. Where
is this basic purpose defined? I can't seem to find a basic purpose for
interfaces called out in the JLS.
It seems to me that an interface has 3 purposes:
To define a reference type
To define an API that implementers must provide implementations for
To define "constants"
It is not a contradiction of the basic purpose to only use it for a subset
of this purposes. For example Serializable and Cloneable only use the first
purpose. Is that a contradiction of the basic purpose of an interface?
I also have trouble when someone says it is wrong to put just constants in
an interface in your client API, because this allows a client to implement
the interface and access the constants. In my opinion, that is an issue for
the client. The fact that I may expose constants in an interface does not
force you to implement the interface.
Some other criticisms that are valid (from the JSR for static import):
"But, inheriting from an interface to get access to
constants in an implementation is a publicly visible operation, and is
therefore
subject to all the rules for binary compatibility when modifying the
constatnts.
Moreover, it requires all other implementations to inherit the same
interface and the same constants,
even though that other implementation may not require them."
Of course. Since the example given was of compile time immediate
assignment, I'm not sure why I'd have to go the extra mile to state the
obvious, but sure, ok.
You were the one that brought up execution speed in terms of choosing one
against the other. I'm only pointing out that it is completely orthogonal to
the entire question. As I said it was a nitpick.
Yes, but not nearly as likely. There is MI of interfaces, not of classes:
If you inherit from a constants class like I discuss, then you are no longer
able to inherit from any other class in the java hierarchy that you would
need.
So what? It is still possible and is likely.
I have been trying to point out that this issue of interface constants is
not the entirety of what enums are about. Enums are compile-time type-safe
constructs, not just ways of holding ints. If not 1.5, then take C++: an
enum element can /evaluate/ to a number, but it is of the enum type when
passing it about. Compile time type-safe.
That's all interesting, but who said anything about enums? I was talking
about static import which is coming in 1.5. See
http://jcp.org/aboutJava/communityprocess/jsr/tiger/static-import.html
This current discussion was about using interfaces to hold merely int
values, which is a related, but separate concern, handled better IMHO with
classes.
But the issue is that it is often undesirably verbose to have to refer to
them using the qualified name every time. When you start having to use a
constant more than once or twice (let's say 20-30 times) it gets really old
to have to qualify it every time. If you have ever done any heavy work with
the Java ByteCode Engineering Library (BCEL) you'd thank your lucky stars
for being able to "implement" the constants interface (See
http://jakarta.apache.org/bcel/apidocs/org/apache/bcel/Constants.html).
Another advantage to declaring constants in an interface is that I don't
have to type the public static final on each of them. I know for certain
that each is unchangeable and that it was explicitly initialized.
There is another alternative to consider here to access constants
unqualified in a class and that is giving them an alias in the class, such
as
class Foo
{
private static final int CONSTANT = Bar.CONSTANT;
Of course this is only viable when using a small number of constants.
But once again the entire argument will be moot in 1.5 with static import.