7

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).

Community
  • 1
  • 1
Tom Tresansky
  • 19,364
  • 17
  • 93
  • 129
  • 4
    The answer is that they are *always* `final`. They are also always `static`. – jbindel Oct 08 '10 at 20:13
  • And fields in interfaces are always _public_ too – Peter Lawrey Oct 08 '10 at 22:43
  • 1
    @BalusC: Editing the title of this question was not appreciated, now the top ranked answer is reiterating basic language definitions...I understand the fields of an interface are public static final, my question was about interfaces themselves. Your edit obscured my intent. – Tom Tresansky Oct 09 '10 at 16:10
  • 1
    A final interface makes no sense. You would not be able to implement it then. Your code example demonstrates a different problem. Otherwise this is just a dupe of the other question. – BalusC Oct 09 '10 at 16:15
  • @Tom: You might want to edit your question itself to better reflect what you're wanting to ask (i.e., about why `A` can't prevent there from being a `B` that inherits from it). – Donal Fellows Oct 09 '10 at 16:36
  • @Donal Fellows: Clarifications added. Hopefully that will help any newcomers who don't feel like tracing through the comment threads. – Tom Tresansky Oct 10 '10 at 14:27

6 Answers6

11

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);

jbindel
  • 5,535
  • 2
  • 25
  • 38
  • 2
    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. – jbindel Oct 08 '10 at 20:07
  • 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 – jbindel Oct 08 '10 at 20:13
  • I understand this. But the value of (some implementation of A).TEST can vary, and perhaps that was not the intent. – Tom Tresansky Oct 09 '10 at 16:19
  • 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. – jbindel Oct 09 '10 at 18:03
  • The examples in the language spec make it even more clear that the values are ts not 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. – jbindel Oct 09 '10 at 18:14
  • 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 Oct 10 '10 at 14:23
  • 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. – jbindel Oct 10 '10 at 15:59
  • Your question is not unclear, but it appears to be based on an incorrect assumption of what is actually going on. – jbindel Oct 10 '10 at 16:07
  • @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 Oct 14 '10 at 15:38
5

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.

Donal Fellows
  • 133,037
  • 18
  • 149
  • 215
Victor Sorokin
  • 11,878
  • 2
  • 35
  • 51
  • Not talking about methods here. Also, I understand constants in interfaces is usually a bad idea, that isn't the issue here. – Tom Tresansky Oct 08 '10 at 19:58
  • 2
    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 Oct 08 '10 at 20:02
  • Ah, I didn't make that connection the first time I read this. Un-down voted. – Tom Tresansky Oct 09 '10 at 16:25
  • 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 Oct 09 '10 at 16:26
  • @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 Oct 09 '10 at 16:32
3

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
  • 67,365
  • 22
  • 157
  • 181
2

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

Ricky Clarkson
  • 2,909
  • 1
  • 19
  • 21
  • 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 Oct 09 '10 at 16:14
  • 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 Oct 09 '10 at 18:34
1

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
  • 525,659
  • 79
  • 751
  • 1,130
0

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.

  • 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 Oct 09 '10 at 16:22
  • 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. – Damian Leszczyński - Vash Oct 09 '10 at 16:36