Durante décadas ha sido el caso de que las interfaces eran solamente única (sólo) para especificar firmas de métodos. Nos dijeron que esta era la "forma correcta de hacer las cosas ™".
Entonces salió Java 8 y dijo:
Bueno, eh, ahora puedes definir métodos predeterminados. Tengo que correr, adiós.
Tengo curiosidad por saber cómo los desarrolladores experimentados de Java y los que comenzaron recientemente (los últimos años) lo están digiriendo. También me pregunto cómo encaja esto en la ortodoxia y práctica de Java.
Estoy creando un código experimental y, mientras realizaba algunas refactorizaciones, terminé con una interfaz que simplemente extiende una interfaz estándar (Iterable) y agrega dos métodos predeterminados. Y voy a ser sincero, me siento muy bien por eso.
Sé que esto es un poco abierto, pero ahora que ha pasado algún tiempo para que Java 8 se use en proyectos reales, ¿hay alguna ortodoxia en torno al uso de métodos predeterminados? Lo que más veo cuando se discuten es sobre cómo agregar nuevos métodos a una interfaz sin romper los consumidores existentes. Pero, ¿qué hay de usar esto desde el principio como el ejemplo que di arriba? ¿Alguien ha tenido algún problema al proporcionar implementaciones en sus interfaces?
fuente
java.util.function.Function
uso de métodos predeterminados en una interfaz completamente nueva.Respuestas:
Un gran caso de uso es lo que yo llamo interfaces de "palanca": interfaces que solo tienen una pequeña cantidad de métodos abstractos (idealmente 1), pero proporcionan mucha "influencia" en el sentido de que le brindan mucha funcionalidad: usted solo necesitas implementar 1 método en tu clase pero obtienes muchos otros métodos "gratis". Piense en una interfaz de recogida, por ejemplo, con un solo extracto
foreach
método ydefault
métodos comomap
,fold
,reduce
,filter
,partition
,groupBy
,sort
,sortBy
, etc.Aquí hay un par de ejemplos. Vamos a empezar con
java.util.function.Function<T, R>
. Tiene un solo método abstractoR apply<T>
. Y tiene dos métodos predeterminados que le permiten componer la función con otra función de dos maneras diferentes, ya sea antes o después. Ambos métodos de composición se implementan utilizando soloapply
:También podría crear una interfaz para objetos comparables, algo como esto:
O un marco de colecciones extremadamente simplificado, donde todas las operaciones de colecciones regresan
Collection
, independientemente del tipo original:Esto se vuelve muy interesante en combinación con lambdas, porque dicha interfaz "palanca" puede ser implementada por un lambda (es una interfaz SAM).
Este es el mismo caso de uso para el que se agregaron los Métodos de extensión en C♯, pero los métodos predeterminados tienen una clara ventaja: son métodos de instancia "adecuados", lo que significa que tienen acceso a detalles de implementación privados de la interfaz (
private
están llegando los métodos de interfaz en Java 9), mientras que los métodos de extensión son solo azúcar sintáctico para los métodos estáticos.Si Java recibiera alguna vez una inyección de interfaz, también permitiría parches de mono modulares, seguros y de tipo seguro. Esto sería muy interesante para los implementadores de lenguaje en la JVM: en este momento, por ejemplo, JRuby hereda o ajusta las clases de Java para proporcionarles semánticas de Ruby adicionales, pero idealmente, quieren usar las mismas clases. Con la inyección de interfaz y los métodos predeterminados, podrían inyectar, por ejemplo, una
RubyObject
interfazjava.lang.Object
, de modo que un JavaObject
y un RubyObject
son exactamente lo mismo .fuente
Comparable
interfaz con un resumencompareTo
método, y por defectolessThan
,lessThanOrEqual
,greaterThan
,greaterThanOrEqual
,isBetween
, yclamp
métodos, todos implementado en términos decompareTo
. O simplemente mirejava.util.function.Function
: tiene unapply
método abstracto y dos métodos de composición predeterminados, ambos implementados en términos deapply
. Intenté dar un ejemplo de unaCollection
interfaz, pero hacer que todo sea seguro para los tipos es complicado y demasiado largo para esta respuesta: intentaré darle una oportunidad a una versión que no sea segura para los tipos y que no conserve los tipos. Manténganse al tanto.