Según tengo entendido, si implementa una interfaz en java, los métodos especificados en esa interfaz deben ser utilizados por las subclases que implementan dicha interfaz.
He notado que en algunas interfaces, como la interfaz de Colección, hay métodos que se comentan como opcionales, pero ¿qué significa esto exactamente? ¿Me ha confundido un poco, ya que pensé que se requerirían todos los métodos especificados en la interfaz?
Respuestas:
Parece haber mucha confusión en las respuestas aquí.
El lenguaje Java requiere que cada método en una interfaz sea implementado por cada implementación de esa interfaz. Período. No hay excepciones para esta regla. Decir "Las colecciones son una excepción" sugiere una comprensión muy vaga de lo que realmente está sucediendo aquí.
Es importante darse cuenta de que hay dos niveles de conformidad con una interfaz:
Lo que puede comprobar el lenguaje Java. Esto básicamente se reduce a: ¿hay alguna implementación para cada uno de los métodos?
Realmente cumpliendo el contrato. Es decir, ¿la implementación hace lo que la documentación de la interfaz dice que debería?
Las interfaces bien escritas incluirán documentación que explique exactamente lo que se espera de las implementaciones. Su compilador no puede verificar esto por usted. Necesita leer los documentos y hacer lo que dicen. Si no hace lo que dice el contrato, tendrá una implementación de la interfaz en lo que respecta al compilador , pero será una implementación defectuosa / no válida.
Al diseñar la API de colecciones, Joshua Bloch decidió que, en lugar de tener interfaces muy precisas para distinguir entre diferentes variantes de colecciones (p. Ej., Legibles, de escritura, de acceso aleatorio, etc.), solo tendría un conjunto de interfaces muy burdas, principalmente
Collection
,List
,Set
yMap
, a continuación, documentar ciertas operaciones como "opcional". Esto fue para evitar la explosión combinatoria que resultaría de interfaces de grano fino. De las preguntas frecuentes sobre el diseño de API de Java Collections :Cuando los métodos en la API de colecciones se documentan como "operaciones opcionales", no significa que puede dejar la implementación del método fuera de la implementación, ni significa que puede usar un cuerpo de método vacío (por un lado, muchos de necesitan devolver un resultado). Más bien, significa que una opción de implementación válida (una que aún cumple con el contrato) es lanzar un
UnsupportedOperationException
.Tenga en cuenta que debido a que
UnsupportedOperationException
es unRuntimeException
, puede lanzarlo desde cualquier implementación de método, en lo que respecta al compilador. Por ejemplo, podría lanzarlo desde una implementación deCollection.size()
. Sin embargo, tal implementación violaría el contrato ya que la documentación paraCollection.size()
no dice que esto esté permitido.Aparte: el enfoque utilizado por la API de colecciones de Java es algo controvertido (probablemente menos ahora que cuando se introdujo por primera vez, sin embargo). En un mundo perfecto, las interfaces no tendrían operaciones opcionales, y en su lugar se usarían interfaces de grano fino. El problema es que Java no admite tipos estructurales inferidos ni tipos de intersección, por lo que intentar hacer las cosas de la "manera correcta" termina siendo extremadamente difícil de manejar en el caso de las colecciones.
fuente
There are no exceptions to this rule
. Preguntándose por qué esta respuesta no está marcada como aceptada. Otros son buenos pero has dado más que suficiente.Foo
que no se implementaRunnable
con el método públicovoid run()
. Ahora crea una claseBar
queextends Foo
yimplements Runnable
sin sobrepasarrun
. Todavía implementa el método, aunque indirectamente. Asimismo, la implementación de un método predeterminado sigue siendo una implementación.remove
se le dio una implementación predeterminada. Si no lo implementa, su clase obtiene la implementación predeterminada. Los otros dos métodos que menciona no tienen implementaciones predeterminadas.Para compilar una clase de implementación (no abstracta) para una interfaz, se deben implementar todos los métodos.
Sin embargo , si pensamos en un método cuya implementación es una simple excepción lanzada como 'no implementado' (como algunos métodos en la
Collection
interfaz), entonces laCollection
interfaz es la excepción en este caso, no el caso normal. Por lo general , la clase de implementación debería (y lo hará) implementar todos los métodos.El "opcional" en la colección significa que la clase de implementación no tiene que 'implementar' (de acuerdo con la terminología anterior), y simplemente arrojará
NotSupportedException
).Un buen ejemplo:
add()
método para colecciones inmutables: el concreto simplemente implementará un método que no hace más que arrojarNotSupportedException
En el caso de
Collection
que se haga para evitar árboles de herencia desordenados, eso hará que los programadores se sientan miserables, pero en la mayoría de los casos, este paradigma no se recomienda y debe evitarse si es posible.Actualizar:
A partir de Java 8, se introdujo un método predeterminado .
Eso significa que una interfaz puede definir un método, incluida su implementación.
Esto se agregó para permitir agregar funcionalidad a las interfaces, sin dejar de admitir la compatibilidad con versiones anteriores de fragmentos de código que no necesitan la nueva funcionalidad.
Tenga en cuenta que el método todavía lo implementan todas las clases que lo declaran, pero utilizando la definición de la interfaz.
fuente
Una interfaz en Java simplemente declara el contrato para implementar clases. Todos los métodos en esa interfaz deben implementarse, pero las clases de implementación son libres de dejarlos sin implementar, es decir, en blanco. Como ejemplo artificial,
Ahora lo he dejado
doSomethingElse()
sin implementar, dejándolo libre para que lo implementen mis subclases. Eso es opcional.Sin embargo, si se trata de interfaces de colección, como han dicho otros, son una excepción. Si ciertos métodos no se implementan y los llama, pueden generar
UnsupportedOperationException
excepciones.fuente
Los métodos opcionales en la interfaz Collection significan que la implementación del método puede generar una excepción, pero debe implementarse de todos modos. Como se especifica en los documentos :
fuente
new Runnable ( ) { @ Override public void run ( ) { throw new UnsupportedOperationException ( ) ; } }
:;add((T)null)
puede ser válido en un caso pero no en otro. Es decir, habla de excepciones / comportamientos opcionales y de argumentos ("restricciones sobre elementos" ... "elemento no elegible" ... "excepciones marcadas como opcionales") y no aborda métodos opcionales .Todos los métodos deben implementarse para que el código se compile (aparte de aquellos con
default
implementaciones en Java 8+), pero la implementación no tiene que hacer nada funcionalmente útil. Específicamente, él:UnsupportedOperationException
(o similar)El último enfoque a menudo se toma en las clases de colección: todos los métodos aún se implementan, pero algunos pueden lanzar una excepción si se llaman en tiempo de ejecución.
fuente
De hecho, me inspira SurfaceView.Callback2. Creo que esta es la forma oficial
Si su clase no necesita implementar métodos opcionales, simplemente "implementa Callback". Si su clase necesita implementar métodos opcionales, simplemente "implementa CallbackExtended".
Perdón por la mierda en inglés.
fuente
En Java 8 y versiones posteriores, la respuesta a esta pregunta sigue siendo válida, pero ahora tiene más matices.
Primero, estas declaraciones de la respuesta aceptada siguen siendo correctas:
Entonces, ¿cuál es el matiz nuevo en Java 8? Cuando se habla de "métodos opcionales", cualquiera de los siguientes es ahora apto:
1. Un método cuya implementación es contractualmente opcional
La "tercera declaración" dice que los métodos de interfaz abstracta siempre deben implementarse y esto sigue siendo cierto en Java 8+. Sin embargo, como en Java Collections Framework, es posible describir algunos métodos abstractos de interfaz como "opcionales" en el contrato.
En este caso, el autor que está implementando la interfaz puede optar por no implementar el método. Sin embargo, el compilador insistirá en una implementación, por lo que el autor usa este código para cualquier método opcional que no sea necesario en la clase de implementación en particular:
En Java 7 y versiones anteriores, este era realmente el único tipo de "método opcional" que existía, es decir, un método que, si no se implementaba, arrojaba una UnsupportedOperationException. Este comportamiento está necesariamente especificado por el contrato de interfaz (por ejemplo, los métodos de interfaz opcionales de Java Collections Framework).
2. Un método predeterminado cuya reimplementación es opcional
Java 8 introdujo el concepto de métodos predeterminados . Estos son métodos cuya implementación puede ser proporcionada por la propia definición de interfaz. Generalmente, solo es posible proporcionar métodos predeterminados cuando el cuerpo del método se puede escribir usando otros métodos de interfaz (es decir, las "primitivas"), y cuando
this
puede significar "este objeto cuya clase ha implementado esta interfaz".Un método predeterminado debe cumplir con el contrato de la interfaz (como debe hacerlo cualquier otra implementación de método de interfaz). Por lo tanto, especificar una implementación del método de interfaz en una clase de implementación queda a discreción del autor (siempre que el comportamiento sea adecuado para su propósito).
En este nuevo entorno, Java Collections Framework podría reescribirse como:
De esta manera, el método "opcional"
add()
tiene el comportamiento predeterminado de lanzar una UnsupportedOperationException si la clase de implementación no proporciona un comportamiento nuevo propio, que es exactamente lo que le gustaría que sucediera y que cumple con el contrato de List. Si un autor está escribiendo una clase que no permite agregar nuevos elementos a una implementación de Lista, la implementación deadd()
es opcional porque el comportamiento predeterminado es exactamente lo que se necesita.En este caso, la "tercera declaración" anterior sigue siendo cierta, porque el método se ha implementado en la propia interfaz.
3. Un método que devuelve un
Optional
resultadoEl último tipo nuevo de método opcional es simplemente un método que devuelve un
Optional
. LaOptional
clase proporciona una forma decididamente más orientada a objetos de tratar losnull
resultados.En un estilo de programación fluido, como el que se ve comúnmente al codificar con la nueva API de Java Streams, un resultado nulo en cualquier punto hace que el programa se bloquee con una NullPointerException. La
Optional
clase proporciona un mecanismo para devolver resultados nulos al código del cliente de una manera que habilita el estilo fluido sin que el código del cliente se bloquee.fuente
Si revisamos el código de AbstractCollection.java en grepCode, que es una clase antecesora para todas las implementaciones de colecciones, nos ayudará a comprender el significado de los métodos opcionales. Aquí está el código para el método add (e) en la clase AbstractCollection. El método add (e) es opcional según la interfaz de recopilación
El método opcional significa que ya está implementado en clases ancestrales y arroja UnsupportedOperationException al ser invocado. Si queremos que nuestra colección sea modificable, entonces debemos anular los métodos opcionales en la interfaz de la colección.
fuente
Bueno, este tema se ha abordado ... sí ... pero piense, falta una respuesta. Estoy hablando de los "métodos predeterminados" de las interfaces. Por ejemplo, imaginemos que tendrá una clase para cerrar cualquier cosa (como un destructor o algo así). Digamos que debería tener 3 métodos. Llamémoslos "doFirst ()", "doLast ()" y "onClose ()".
Entonces decimos que queremos que cualquier objeto de ese tipo al menos se dé cuenta de "onClose ()", pero los otros son opcionales.
Puede darse cuenta de eso, utilizando los "Métodos predeterminados" de las interfaces. Lo sé, la mayoría de las veces esto anularía la razón de una interfaz, pero si está diseñando un marco, esto puede ser útil.
Entonces, si desea realizarlo de esta manera, se vería como sigue
¿Qué pasaría ahora? Si, por ejemplo, lo implementaras en una clase llamada "Prueba", el compilador estaría perfectamente bien con lo siguiente:
con la Salida:
o
con la salida:
Todas las combinaciones son posibles. Todo lo que tenga "predeterminado" se puede implementar, pero no se debe implementar, sin embargo, se debe implementar cualquier cosa que no tenga.
Espero que no sea del todo incorrecto que ahora responda.
¡Que tengas un gran día a todos!
[edit1]: Nota: esto solo funciona en Java 8.
fuente
Estaba buscando una forma de implementar la interfaz de devolución de llamada, por lo que era necesario implementar métodos opcionales, ya que no quería implementar todos los métodos para cada devolución de llamada.
Entonces, en lugar de usar una interfaz, usé una clase con una implementación vacía como:
Y puede configurar la variable miembro CallBack de esta manera,
entonces llámalo así.
De esta manera, no tendrá que preocuparse por implementar todos los métodos por devolución de llamada, sino solo anular los que necesita.
fuente
A pesar de que no responde a la pregunta de la OP, vale la pena señalar que a partir del 8 de Java añadiendo métodos predeterminados a las interfaces de hecho es factible . La
default
palabra clave colocada en la firma del método de una interfaz dará como resultado que una clase tenga la opción de anular el método, pero no lo requiera.fuente
Tutorial de colecciones Java de Oracle:
fuente