¿Por qué Java no permite miembros privados en la interfaz? ¿Existe alguna razón en particular?
¿Por qué Java no permite miembros privados en la interfaz? ¿Existe alguna razón en particular?
Respuestas:
Desde Java Language Spec, (Control de acceso) :
"El lenguaje de programación Java proporciona mecanismos para el control de acceso, para evitar que los usuarios de un paquete o clase dependan de detalles innecesarios de la implementación de ese paquete o clase".
El control de acceso consiste en ocultar los detalles de implementación. Una interfaz no tiene ninguna implementación que ocultar.
En Java 9, los métodos privados en las interfaces son posibles.
El equipo del compilador de javac se complace en anunciar la disponibilidad del soporte del compilador para métodos privados en interfaces que comienzan con la compilación 9 b54 de JDK.
Los métodos de interfaz privada son parte de Java 9 como parte de JEP-213 . Dado que las interfaces en Java 8 pueden tener métodos predeterminados , los métodos privados permiten que varios métodos predeterminados utilicen un método privado compartido.
A partir de Java 8, las interfaces pueden tener métodos predeterminados, y a partir de Java 9, se permite que una interfaz tenga métodos privados a los que solo se puede acceder mediante métodos predeterminados en la misma interfaz.
Una interfaz se usa para describir una API que es proporcionada por cualquier clase que implemente la interfaz. Dado que una interfaz de su definición no tiene estado, no tiene sentido declarar miembros de campo en ella.
No habría forma de implementar tal interfaz. Una respuesta a una pregunta que planteé sugiere fuertemente que sería imposible (sin cambiar radicalmente las reglas) implementar una interfaz con métodos privados; esto deja abierta la pregunta de por qué no se permiten los métodos privados protegidos y los paquetes.
class OuterClass
{
void run ( MyInterface x )
{
x . publicMethod ( ) ; // why not?
x . protectedMethod ( ) ; // why not?
x . packagePrivateMethod ( ) ; // why not?
x . privateMethod ( ) ; // why not?
}
interface MyInterface
{
public abstract void publicMethod ( ) ; // OK
protected abstract void protectedMethod ( ) ; // why not?
abstract void packagePrivateMethod ( ) ; // in interface default is public, but why not package private
private void privateMethod ( ) ; // impossible to implement
}
class MyImpl implements MyInterface
{
public void publicMethod ( ) { } // ok
protected void protectedMethod ( ) { } // no sweat
void packagePrivateMethod ( ) { } // no sweat
private void privateMethod ( ) { } // not happening
}
}
El siguiente código debería lograr el resultado deseado. Aunque todos los métodos son públicos, solo el método público es efectivamente público. El método protegido está efectivamente protegido. packagePrivateMethod es efectivamente packagePrivate. privateMethod es efectivamente privado.
class WorkAround
{
void run ( MyPrivateInterface x )
{
x . publicMethod ( ) ;
x . protectedMethod ( ) ;
x . packagePrivateMethod ( ) ;
x . privateMethod ( ) ;
}
public interface MyPublicInterface { void publicMethod ( ) ; }
protected interface MyProtectedInterface extends MyPublicInterface { void protectedMethod ( ) ; }
interface MyPackagePrivateInterface extends MyProtectedInterface { void packagePrivateMethod ( ) ; }
private interface MyPrivateInterface extends MyPackagePrivateInterface { void privateMethod ( ) ; }
}
Según el Javalenguaje de programación, el alcance del private membersestá limitado al classen el que se declara y solo se puede acceder a él mediante métodos de ese class. Pero intefaceno tiene un cuerpo de método, por lo tanto, no sirve de nada declarar miembros privados dentro de un interface.
Java permite métodos privados en una interfaz en Java 9 . Los métodos predeterminados se introdujeron en Java 8. Es posible que varios métodos predeterminados quieran compartir algún código, entonces este código se puede mover a un método privado sin exponerlo al mundo exterior. Este error se ha corregido y, a partir de JDK 9 build 54, se ha resucitado el soporte del compilador para métodos de interfaz privada.
public interface IData{
default void processData(int data) {
validate(data);
// do some work with it
}
default void consumeData(int data) {
validate(data);
// do some work with it
}
private void validate(int data) {
// validate data
}
}
Es porque serían inútiles.
No habría forma de llamar a un método privado.
Los miembros privados son un detalle de implementación. Una interfaz trata sobre el rol público que puede asumir una clase.
los campos privados no serían completamente inútiles ya que otros campos y clases internas podrían acceder a ellos.
Sin embargo, los métodos privados no se pudieron implementar, incluso en clases anidadas, haciéndolos casi inútiles. Podrías leerlos usando la reflexión, pero eso es más bien un caso marginal.
Los miembros de una clase que se declaran privados no son heredados por subclases de esa clase. Solo los miembros de una clase que están declarados protegidos o públicos son heredados por subclases declaradas en un paquete diferente al que se declara la clase.
Fuente
Entonces, no tiene ningún método de trabajo en una interfaz que pueda funcionar con ese campo privado no heredable. Entonces, ¿por qué debería existir?
Sí, no puedo hacer eso. Para todos aquellos que comentan por qué no debería:
Imagine que tengo la clase A, que utiliza la interfaz I.La clase B, extiende la clase A, por lo tanto, también hereda todos los métodos de interfaz en A.
Ahora, imagine que quiero un método privado en la Clase A, pero también lo quiero definido contractualmente para otras clases (tal vez una clase C, que no necesariamente extiende la Clase B o A).
Quizás para un método de "inicialización", que quiero para todas las clases que usan una interfaz I. Pero, obviamente, no quiero que un método de inicialización sea público ... ya que solo debe usarse una vez, o como la clase lo considere necesario, no solo porque quiera usarlo todo.
La única solución es una solución alternativa, o simplemente forzando el método init en las clases mismas sin una interfaz.
No entiendo la razón también, seguro, pero aún así, a veces puede ser útil. Claramente, Oracle está de acuerdo, ya que permiten métodos de interfaz privados en JDK 9.
Lo que hice, para el mío de todos modos, fue colocar una variable booleana simple, de esa manera el método de interfaz (que debería ser privado) se puede marcar como verdadero (inicializado = verdadero) después de establecerse una vez. Luego, cuando se vuelve a llamar, el método simplemente no hace nada. De esta manera, el método de la interfaz se puede implementar como público, pero como el constructor (de mi clase) llama al método primero, esto establece la variable en verdadera, por lo que no se puede volver a llamar.
De lo contrario, tendría que probar una solución alternativa diferente si solo desea que el funcionamiento interno de la clase lo use ... quizás un método en sí mismo activa y desactiva una bandera a medida que lo usa. Cuando la bandera es falsa, el método no hace nada (esto sería cuando alguien lo llama desde fuera de la clase). Sin embargo, cuando los métodos propios de las clases lo llaman, rápidamente establecen la bandera en verdadero, luego llaman al método y luego establecen la bandera en falso
Al final un poco mudo. Probablemente sea mejor por ahora simplemente colocar la clase privada en la clase misma y cortar la interfaz por completo.