2010-10-08 9 views
7

La extensión de una interfaz simplemente agrega operaciones adicionales para ser definidas en cualquier implementador y no puede romper ninguna implementación existente (a diferencia de extender una clase). Pero puede cambio (EDIT 3 QUE CONSTANTES) y, por lo tanto, el valor PERCIEVED de las constantes (EDIT 2 SEGÚN LAS CLASES DE IMPLEMENTACIÓN).¿Por qué no hay interfaces finales en Java?

Por ejemplo, los siguientes:

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

rendimientos 7, cuando tal vez la intención de interfaz A era que cualquier aplicación de A contiene un campo de test valor de 6.

Si A fuese declaró final podríamos estar seguros de que todas las implementaciones de A ven el mismo valor de test.

¿Alguien entiende por qué esto no es posible?

  • P.S .: Esta es NO un duplicado de this question, sé que no puede ser definitiva, estoy interesado en la idea detrás de la decisión de diseño que condujo a este resultado.

  • P.P.S .: Entiendo constantes en interfaces es generalmente una mala idea, que no es el problema aquí.

EDIT: Por favor, compruebe el historial de revisión, fue editado el título de esta pregunta de una manera que no refleja la intención de la pregunta. Perdón por todos los que respondieron la pregunta que no estaba preguntando. Sí, los campos de la interfaz son implícitamente públicos estáticos, por desgracia, eso no es lo que más me interesa.

EDIT 2 ser absolutamente claro: esta pregunta es acerca de por qué no puede un bloque de interfaz de otras interfaces de extenderlo (por ser final de o algún equivalente).

+4

La respuesta es que son siempre * * 'final'. También son siempre 'estáticos'. – jbindel

+0

Y los campos en las interfaces siempre son _public_ too –

+1

Downvote. La pregunta se basa en una premisa falsa. – EJP

Respuesta

5

El propósito principal de la interfaz no es ser un contenedor de constantes, es definir algunas API que se implementarán mediante clases concretas.

Y, a partir de una especificación lang (9.4. Abstract method declarations):

Tenga en cuenta que un método declarado en una interfaz no debe ser declarada final o se produce un error en tiempo de compilación.Sin embargo, un método declarado en una interfaz puede implementarse mediante un método que se declara final en una clase que implementa la interfaz.

+0

No estoy hablando de métodos aquí. Además, entiendo que las constantes en las interfaces usualmente son una mala idea, ese no es el problema aquí. –

+2

Pero, si pudieras definir toda la interfaz como 'final', significaría que todos los métodos de la interfaz son' finales' también. Y eso está prohibido por especificaciones explícitamente. –

+0

Ah, no hice esa conexión la primera vez que leí esto. Desciende abajo votado. –

3

Según tengo entendido, no se supone que las interfaces impongan restricciones a las implementaciones. Se supone que definen contrato (API).
A partir de este punto, ambos métodos doIt y constante TEST son elementos de API. Sabemos cómo usarlos, pero no sabemos qué hay dentro.
Y cómo exactamente se implementa el método doIt en InterfacesTest o qué valor exacto constante TEST tiene - detalles de implementación.

+0

Es extraño pensar en el valor de una constante como un detalle de implementación, pero supongo que tiene sentido ... –

0

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

Puede ser que usted mismo ha contestado por escrito que se trate.

Tampoco puede crear una clase abstracta final, porque para tener sentido debe implementarse, lo mismo ocurre con la interfaz que debe implementarse por alguna clase.

+0

Las interfaces pueden ser útiles incluso si ninguna clase las implementa. Pueden ser contenedores para constantes. Probablemente esta no sea una gran idea, pero está lejos de ser inaudito. –

+0

Por supuesto, pero en mi humilde opinión, esta es una mala práctica, ese desarrollador debe evitar. En aras de la idea, decir que si puedes hacer algo no significa que debas hacerlo. –

11

Es es final. De hecho, es public static final incluso si no los declaras. Lo que estás haciendo no está anulando la variable constante; usted es que oculta la versión de la interfaz principal.

Compruébelo, el A.TEST no se reemplaza. Todavía es 6.

System.out.println (A.TEST);

+2

Además, puede hacer lo mismo con las clases. Declare su 'static static int final A = 6' en el padre y luego redefinirlo en una subclase como' public static final int A = 7'. Esto se llama * ocultar * en lugar de anular porque la versión de la clase principal está oculta, a menos que usted lo especifique. – jbindel

+0

Aquí hay un enlace con ejemplos de ocultar variables de clase. http://java.sun.com/docs/books/jls/third_edition/html/classes.html#8.3.3.1 – jbindel

+0

Entiendo esto. Pero el valor de (alguna implementación de A) .TEST puede variar, y quizás esa no era la intención. –

2

Tiene dos variables llamadas TEST, no una. No prevalece ninguna anulación. La anulación es solo para métodos.

+0

¿Quién mencionó que prevalece WAS? Estoy confundido con lo que estás respondiendo. Por favor, vea el ejemplo y vuelva a leer la pregunta, desafortunadamente el título fue editado ... –

+0

Usted parece estar asumiendo que hay dos valores para TEST, uno que A ve y uno que B ve. De hecho, hay dos variables llamadas TEST. Tu suposición me lleva a adivinar que piensas que B anula A.TEST. InterfacesTest usa B's TEST como se define en el JLS. –

1

métodos finales no pueden ser anulados.

final evita que se modifique un campo, pero no impide que se oculte. Nota: No puede anular un campo.

En su caso A.TEST está oculto por B.TEST embargo

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

imprimiría

6 
7 
+0

Correcto, entiendo eso. Sin embargo, mi preocupación es el valor de InterfacesTest.TEST. –

+0

InterfacesTest extiende B y no lo oculta así que TEST es 7. –

Cuestiones relacionadas