views:

276

answers:

6

Extending an interface simply adds additional operations to be defined in any implementors and cannot break any existing implementations (unlike extending a class). But it can change (EDIT 3 WHICH CONSTANTS) and hence the PERCIEVED value of constants (EDIT 2 AS SEEN BY THE IMPLEMENTATION CLASSES).

For instance, the following:

interface A {
  int TEST = 6;
}

interface B extends A {
  int TEST = 7;
}

public class InterfacesTest implements B {
  public static void main(final String[] args) {
    System.out.println(TEST);
  }
}

yields 7, when perhaps the intent of interface A was that any implementation of A contain a test field valued at 6.

If A were to be declared final we could be assured all implementations of A see the same value of test.

So does anyone understand why this isn't possible?

  • P.S.: This is NOT a duplicate of this question, I know they can't be final, I'm interested in the thinking behind the design decision that led to this outcome.

  • P.P.S.: I understand constants in interfaces is usually a bad idea, that isn't the issue here.

EDIT: Please check the revision history, the title of this question was edited in a way which did not reflect the question's intent. Sorry to everyone who answered the question I wasn't asking. Yes, interface fields are implicitly public static final, unfortunately that's not what I'm interested in at all.

EDIT 2 To be absolutely clear: this question is about why can't an interface block other interfaces from extending it (by being final or some equivalent).

+3  A: 

As I understand it, interfaces aren't supposed to place restrictions on implementations. They are supposed to define contract (API).
From this point, both method doIt and constant TEST are elements of API. We know how to use them, but we don't know what's inside.
And how exactly method doIt is implemented in InterfacesTest or what exact value constant TEST has - implementation details.

Nikita Rybak
Weird to think of the value of a constant as an implementation detail, but I suppose that sort of makes sense...
Tom Tresansky
+3  A: 

Primary purpose of interface is not being a container of constants, it's to define some APIs which to be implemented by concrete classes.

And, from a lang spec (9.4. Abstract method declarations):

Note that a method declared in an interface must not be declared final or a compile-time error occurs. However, a method declared in an interface may be implemented by a method that is declared final in a class that implements the interface.

Victor Sorokin
Not talking about methods here. Also, I understand constants in interfaces is usually a bad idea, that isn't the issue here.
Tom Tresansky
But, if you could define whole interface as `final`, it would mean that all interface's methods are `final` too. And that is prohibited by spec explicitly.
Victor Sorokin
Ah, I didn't make that connection the first time I read this. Un-down voted.
Tom Tresansky
Sorry...it won't let me un-down vote...says I'm locked in unless you edit the answer. You might want to edit the answer... ;-)
Tom Tresansky
@Victor: I bet that's it, though it would have been entirely possible for the language spec to state that a `final` interface doesn't make its methods final, but rather mean just that the interface can't be extended. I suppose that that wouldn't have been all that useful though; would it have prevented having anything else declared on the implementation class (i.e., "extending" the interface)? The more I try to think what it might mean, the more I feel glad that `final` isn't used on interfaces overall. :-)
Donal Fellows
+1 for actually addressing the question.
Donal Fellows
A: 

If A were to be declared final we could be assured all implementations of A see the same value of test.

May be that You have answered yourself writing that question.

You can't also create a final abstract class, because to have sense it must be implemented, same thing goes for interface it has to be implemented by some class.

Vash
Interfaces can be useful even if no class implements them. They can be containers for constants. This is probably not usually a great idea, but it's far from unheard of.
Tom Tresansky
Off course, but IMHO this is a bad practice, that developer should avoid. In sake of idea saying that if you can do something doesn't mean that you should.
Vash
+10  A: 

It is final. In fact, it's public static final even if you don't declare those. What you are doing is not overriding the constant variable; you are hiding the parent interface's version.

Check it out, the A.TEST is not overridden. It's still 6.

System.out.println(A.TEST);

Fly
Furthermore, you can do the same with classes. Declare your `public static final int A = 6` in the parent and then redefine it in a subclass as `public static final int A = 7`. This is called *hiding* rather than overriding because the parent class's version is hidden unless you specify it.
Fly
Here's a link with examples of hiding class variables. http://java.sun.com/docs/books/jls/third_edition/html/classes.html#8.3.3.1
Fly
I understand this. But the value of (some implementation of A).TEST can vary, and perhaps that was not the intent.
Tom Tresansky
You can't assign another value to any of the TEST variables. You can only create new TEST variables with different values. Each of the *two* values are set once when initialized. What varies is not the value of A.TEST, but instead which TEST variable you are referring to, depending on which is visible and which is hidden.
Fly
The examples in the language spec make it even more clear that the values are tsnot changing in your example. For example, you could define B.TEST as a `String`, which shows that they really are different variables, just as you can hide member variables with local variables. When your code *hides* variables, you just have to be more explicit about which one you want. For example, with a local hiding a member, you use `this` to access the member. There's nothing weird going on.
Fly
I think I should have said in my original post: "But it can change the value of constants AS SEEN FROM THE IMPLEMENTATION CLASS". Sorry if I was unclear.
Tom Tresansky
I think it would be more correct to say, "But it can change which variables are seen in the implementing class." It's not the values seen but the *variables* seen. As long as you view it as *values* changing, you're thinking about this the wrong way. The value of any final variable (primitive or actual reference) simply does not change.
Fly
Your question is not unclear, but it appears to be based on an incorrect assumption of what is actually going on.
Fly
@Fly: I get your point. I should be more precise in my language, the values never change, the implementation class just sees different variables (which always have the same values). That said, if the interface couldn't be extended, you would always see the same variables (and hence the same values)...which is what I have been trying (failing) to ask here.
Tom Tresansky
+2  A: 

You have two variables named TEST, not one. No overriding is taking place. Overriding is only for methods.

Ricky Clarkson
Who mentioned that overriding WAS taking place? I'm confused what you're answering. Please see the example and re-read the question, the title was unfortunately edited...
Tom Tresansky
You seem to be assuming that there are two values for TEST, one that A sees and one that B sees. In fact, there are two variables named TEST. Your assumption leads me to guess that you think B overrides A.TEST. InterfacesTest uses B's TEST as defined in the JLS.
Ricky Clarkson
+1  A: 

final methods cannot be overriden.

final prevents a field being changed, but doesn't prevent it being hidden. Note: You cannot override a field.

In your case A.TEST is hidden by B.TEST however

System.out.println(A.TEST); 
System.out.println(B.TEST); 

would print

6
7
Peter Lawrey
Right, I understand that. However, my concern is the value of InterfacesTest.TEST.
Tom Tresansky
InterfacesTest extends B and does not hide it so TEST is 7.
Peter Lawrey