icon - ¿Cuál es el propósito de la palabra clave predeterminada en Java?
set icon java (8)
Una interfaz en Java es similar a una clase, pero el cuerpo de una interfaz solo puede incluir métodos abstractos y campos
final
(constantes).
Recientemente, vi una pregunta, que se ve así
interface AnInterface {
public default void myMethod() {
System.out.println("D");
}
}
Según la definición de la interfaz,
solo
se permiten
métodos abstractos
.
¿Por qué me permite compilar el código anterior?
¿Cuál es la palabra clave
default
?
Por otro lado, cuando intentaba escribir el siguiente código, dice que el
modifier default not allowed here
default class MyClass{
}
en lugar de
class MyClass {
}
¿Alguien puede decirme el propósito de la palabra clave
default
?
¿Solo se permite dentro de una interfaz?
¿En qué difiere del
default
(sin modificador de acceso)?
Algo que se pasó por alto en las otras respuestas fue su papel en las anotaciones.
Ya en Java 1.5, la palabra clave
default
surgió como un medio para
proporcionar un valor predeterminado
para un campo de anotación.
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface Processor {
String value() default "AMD";
}
Su uso se sobrecargó con la introducción de Java 8 para permitir que uno defina un método predeterminado en las interfaces.
Algo más que se pasó por alto: la razón por la que la
default class MyClass {}
declaración
default class MyClass {}
no es válida se debe a la forma en que
se declaran las clases
.
No hay ninguna disposición en el idioma que permita que esa palabra clave aparezca allí.
Sin
embargo
,
sí
aparece para las
declaraciones de métodos de interfaz
.
Encontrará una muy buena explicación en The Java ™ Tutorials , parte de la explicación es la siguiente:
Considere un ejemplo que involucra a fabricantes de automóviles controlados por computadora que publican interfaces estándar de la industria que describen qué métodos pueden invocarse para operar sus automóviles. ¿Qué pasa si esos fabricantes de automóviles controlados por computadora agregan nuevas funcionalidades, como el vuelo, a sus automóviles? Estos fabricantes necesitarían especificar nuevos métodos para permitir que otras compañías (como los fabricantes de instrumentos de guía electrónica) adapten su software a los autos voladores. ¿Dónde declararían estos fabricantes de automóviles estos nuevos métodos relacionados con el vuelo? Si los agregan a sus interfaces originales, entonces los programadores que han implementado esas interfaces tendrían que reescribir sus implementaciones. Si los agregan como métodos estáticos, los programadores los considerarían como métodos de utilidad, no como métodos esenciales esenciales.
Los métodos predeterminados le permiten agregar nuevas funciones a las interfaces de sus bibliotecas y garantizar la compatibilidad binaria con el código escrito para versiones anteriores de esas interfaces.
Es una nueva característica en Java 8 que permite que una
interface
proporcione una implementación.
Descrito en Java 8
JLS-13.5.6.
Declaraciones de método de interfaz
que lee (en parte)
Agregar un método
default
, o cambiar un método deabstract
adefault
, no rompe la compatibilidad con los binarios preexistentes, pero puede causar unIncompatibleClassChangeError
si un binario preexistente intenta invocar el método. Este error ocurre si el tipo de calificación,T
, es un subtipo de dos interfaces,I
yJ
, dondeI
yJ
declaran un métododefault
con la misma firma y resultado, y niI
niJ
son una subinterfaz de la otra.
What''s New in JDK 8 dice (en parte)
Los métodos predeterminados permiten agregar nuevas funciones a las interfaces de las bibliotecas y garantizan la compatibilidad binaria con el código escrito para versiones anteriores de esas interfaces.
La nueva característica
Java 8
(
Métodos predeterminados
) permite que una interfaz proporcione una implementación cuando se etiqueta con la palabra clave
default
.
Por ejemplo:
interface Test {
default double getAvg(int avg) {
return avg;
}
}
class Tester implements Test{
//compiles just fine
}
La Prueba de interfaz utiliza la palabra clave predeterminada que permite que la interfaz proporcione una implementación predeterminada del método sin la necesidad de implementar esos métodos en las clases que usan la interfaz.
Compatibilidad con versiones anteriores: imagine que su interfaz es implementada por cientos de clases, modificando esa interfaz obligará a todos los usuarios a implementar el método recién agregado, aunque no es esencial para muchas otras clases que implementan su interfaz.
Hechos y restricciones:
1-Solo se puede declarar dentro de una interfaz y no dentro de una clase o clase abstracta.
2-Debe proporcionar un cuerpo
3-No se supone que sea público o abstracto como otros métodos normales utilizados en una interfaz.
Los métodos predeterminados en una interfaz nos permiten agregar nuevas funcionalidades sin romper el código antiguo.
Antes de Java 8, si se agregaba un nuevo método a una interfaz, entonces todas las clases de implementación de esa interfaz estaban destinadas a anular ese nuevo método, incluso si no usaban la nueva funcionalidad.
Con Java 8, podemos agregar la implementación predeterminada para el nuevo método utilizando la palabra clave
default
antes de la implementación del método.
Incluso con clases anónimas o interfaces funcionales, si vemos que algún código es reutilizable y no queremos definir la misma lógica en todas partes del código, podemos escribir implementaciones predeterminadas de esos y reutilizarlos.
Ejemplo
public interface YourInterface {
public void doSomeWork();
//A default method in the interface created using "default" keyword
default public void doSomeOtherWork(){
System.out.println("DoSomeOtherWork implementation in the interface");
}
}
class SimpleInterfaceImpl implements YourInterface{
/*
* Not required to override to provide an implementation
* for doSomeOtherWork.
*/
@Override
public void doSomeWork() {
System.out.println("Do Some Work implementation in the class");
}
/*
* Main method
*/
public static void main(String[] args) {
SimpleInterfaceImpl simpObj = new SimpleInterfaceImpl();
simpObj.doSomeWork();
simpObj.doSomeOtherWork();
}
}
Los métodos predeterminados le permiten agregar nuevas funcionalidades a las interfaces de sus aplicaciones. También se puede usar para tener una herencia múltiple . Además de los métodos predeterminados, puede definir métodos estáticos en las interfaces. Esto facilita la organización de los métodos auxiliares.
Los métodos predeterminados se agregaron a Java 8 principalmente para admitir expresiones lambda. Los diseñadores (inteligentemente, en mi opinión) decidieron hacer la sintaxis lambdas para crear implementaciones anónimas de una interfaz. Pero dado que las lambdas solo pueden implementar un método único, se limitarían a las interfaces con un método único, lo que sería una restricción bastante severa. En cambio, se agregaron métodos predeterminados para permitir el uso de interfaces más complejas.
Si necesita algo convincente de la afirmación de que el
default
se introdujo debido a las lambdas, tenga en cuenta que la
propuesta
del
hombre de paja
del Proyecto Lambda, de Mark Reinhold, en 2009, menciona los ''Métodos de extensión'' como una característica obligatoria que se debe agregar para admitir lambdas.
Aquí hay un ejemplo que demuestra el concepto:
interface Operator {
int operate(int n);
default int inverse(int n) {
return -operate(n);
}
}
public int applyInverse(int n, Operator operator) {
return operator.inverse(n);
}
applyInverse(3, n -> n * n + 7);
Muy ingenioso, me doy cuenta, pero debería ilustrar cómo
default
soporta lambdas.
Debido a que
inverse
es un valor predeterminado, una clase de implementación puede anularlo fácilmente si es necesario.
Se introduce un nuevo concepto en Java 8 llamado métodos predeterminados. Los métodos predeterminados son aquellos que tienen una implementación predeterminada y ayudan a evolucionar las interfaces sin romper el código existente. Veamos un ejemplo:
public interface SimpleInterface {
public void doSomeWork();
//A default method in the interface created using "default" keyword
default public void doSomeOtherWork(){
System.out.println("DoSomeOtherWork implementation in the interface");
}
}
class SimpleInterfaceImpl implements SimpleInterface{
@Override
public void doSomeWork() {
System.out.println("Do Some Work implementation in the class");
}
/*
* Not required to override to provide an implementation
* for doSomeOtherWork.
*/
public static void main(String[] args) {
SimpleInterfaceImpl simpObj = new SimpleInterfaceImpl();
simpObj.doSomeWork();
simpObj.doSomeOtherWork();
}
}
y la salida es:
Implementar algo de trabajo en la clase
Implementación DoSomeOtherWork en la interfaz