Anidamiento con interfaces Java

Si ha leído mi tutorial de Java 101 que presenta clases estáticas y clases internas, debe estar familiarizado con los conceptos básicos para trabajar con clases anidadas en código Java. En este consejo de Java, aprenderá tres formas comunes de utilizar técnicas de anidamiento con interfaces Java. También demostraré brevemente las interfaces de anidación con métodos estáticos, también conocidos como interfaces de métodos estáticos.

Más sobre interfaces Java

Para obtener una introducción a las interfaces de Java, incluida la diferencia entre clases e interfaces, consulte mi tutorial de Java 101 Trabajar con interfaces en Java.

Anidar interfaces en clases

Java te permite declarar interfaces dentro de clases. Una vez declarada, una interfaz es automáticamente un miembro estático de la clase. No es necesario declarar la interfaz con la staticpalabra clave. Considere el siguiente ejemplo:

 class EnclosingClass { interface EnclosedInterface1 { } static interface EnclosedInterface2 { } } 

EnclosedInterface1y EnclosedInterface2son interfaces miembro estáticas . No hay equivalente a las clases locales porque las interfaces no se pueden declarar en bloques. Sin embargo, las interfaces se pueden utilizar en contextos de clase anónimos.

Por lo general, no se accede a las interfaces anidadas desde más allá de sus clases adjuntas. De lo contrario, podría declararlos como interfaces de nivel superior . En cambio, se accede a ellos desde el interior de sus clases adjuntas, como se demuestra aquí:

 class EnclosingClass { interface EnclosedInterface1 { } static interface EnclosedInterface2 { } static class EnclosedClass1 implements EnclosedInterface1, EnclosedInterface2 { } class EnclosedClass2 implements EnclosedInterface1, EnclosedInterface2 { } void m() { class EnclosedClass3 implements EnclosedInterface1, EnclosedInterface2 { } new EnclosedInterface1() { }; } } 

Tenga en cuenta que la clase de miembro estático, la clase de miembro EnclosedClass1no estática EnclosedClass2y la clase local EnclosedClass3implementan ambas interfaces anidadas. Sin embargo, solo se puede implementar una interfaz en un contexto de clase anónimo. (Consulte Clases estáticas y clases internas en Java para obtener más información sobre las clases anónimas).

Clases con interfaces anidadas en java.net

La biblioteca de clases estándar de Java incluye clases con interfaces anidadas. Por ejemplo, InetAddress(en el java.netpaquete), que representa una dirección de Protocolo de Internet, declara una Addressesinterfaz privada implementada por clases de miembros privados CachedAddressesy NameServiceAddressesestáticos. También declara una NameServiceinterfaz privada implementada por clases de miembros privados PlatformNameServicey HostsFileNameServiceestáticos.

Anidar interfaces en interfaces

Java también te permite declarar interfaces dentro de interfaces. En este caso, una interfaz anidada es un miembro estático de su interfaz envolvente y, una vez más, la staticpalabra clave es redundante. Además, la interfaz anidada es implícitamente pública. He aquí un ejemplo:

 interface EnclosingInterface { interface EnclosedInterface1 // implicitly static and public { } static interface EnclosedInterface2 // explicitly static and implicitly public { } } 

Puede acceder a una interfaz adjunta poniendo el prefijo de su nombre con el nombre de la interfaz adjunta y el operador de acceso de miembros. Por ejemplo, especifique EnclosingInterface.EnclosedInterface1para acceder EnclosedInterface1.

Interfaces anidadas en el marco de colecciones de Java

Java Collections Framework proporciona información sobre la utilidad de anidar una interfaz en otra. Considere la java.util.Mapinterfaz, que describe un mapa (una colección de pares clave-valor). La Mapinterfaz abstrae lo que significa ser un mapa. Clases como HashMape java.util.TreeMapimplementar Map, que describen diferentes tipos de implementaciones de mapas.

Mapdeclara Entrycomo uno de sus miembros. Entryes una interfaz anidada que describe un par clave-valor. La Entryinterfaz se declara Mapdebido a la estrecha relación entre las dos interfaces: cada entrada debe pertenecer a un mapa. Entryes implementado por la java.util.AbstractMapclase SimpleEntryy las SimpleImmutableEntryclases miembro estáticas. Por lo general, ignorará estas clases de miembros estáticos e interactuará con ellas Map.Entry.

Clases anidadas en interfaces

Una de las características más extrañas del lenguaje de Java es la capacidad de anidar una clase dentro de una interfaz. Al igual que con una interfaz anidada, la clase anidada es implícitamente pública y estática. He aquí un ejemplo:

 interface EnclosingInterface { class EnclosedClass { } } 

A pesar de su rareza, poder anidar una clase dentro de una interfaz puede ser útil, especialmente cuando existe una relación estrecha entre la interfaz adjunta y la clase adjunta. La captura de esta relación mejora la legibilidad del código fuente. En los casos en que la clase y la interfaz llevan el mismo nombre, el anidamiento también puede ayudarlo a evitar un conflicto de nombres entre los dos.

Ejemplo: la interfaz direccionable incluye la clase de dirección

Suponga que desea modelar entidades direccionables como cartas, postales y paquetes. Cada entidad será descrita por su propia clase, pero todas comparten el rasgo común de ser direccionables a algún destino. Cada clase podría diseñarse con campos de dirección duplicados, o podría abstraer estos detalles en una superclase común. Alternativamente, puede aprovechar la Addressableinterfaz del Listado 1 .

Listado 1. Addressable.java

 public interface Addressable { public class Address { private String boxNumber; private String street; private String city; public Address(String boxNumber, String street, String city) { this.boxNumber = boxNumber; this.street = street; this.city = city; } public String getBoxNumber() { return boxNumber; } public String getStreet() { return street; } public String getCity() { return city; } public String toString() { return boxNumber + " - " + street + " - " + city; } } public Address getAddress(); } 

La Addressableinterfaz describe una entidad direccionable que contiene una dirección. Esta dirección está descrita por la Addressclase anidada . El getAddress()método es implementado por cualquier clase que implemente Addressable.

El Listado 2 presenta el código fuente a una Letterclase que implementa Addressable.

Listado 2. Letter.java

 public class Letter implements Addressable { private Addressable.Address address; public Letter(String boxNumber, String street, String city) { address = new Addressable.Address(boxNumber, street, city); } public Address getAddress() { return address; } } 

Letteralmacena un solo addresscampo de tipo Addressable.Address. Esta clase anidada es instanciada por Letterel constructor. El getAddress()método implementado devuelve este objeto.

Ahora considere lo que sucede cuando agregamos clases Postcardy Parcela la Addressablesaplicación. Listado 3 presenta el código fuente a una Addressablesaplicación, lo que demuestra las Postcard, Parcely Lettertipos.

Listado 3. Addressables.java

 public class Addressables { public static void main(String[] args) { Addressable[] addressables = { new Letter("100", "Main Street", "Town A"), new Postcard("200", "Waterfront Drive", "Town B"), new Parcel("300", "10th Ave", "Town C") }; for (int i = 0; i < addressables.length; i++) System.out.println(addressables[i].getAddress()); } }

The main() method first creates an array of Addressable objects. It then iterates over these objects, invoking getAddress() on each object. The returned Addressable.Address object's toString() method is invoked by System.out.println() to return a string representation of the object, and this representation is subsequently output.

Compile Listings 2 and 3 along with Postcard.java and Parcel.java as follows:

 javac *.java 

Run the application as follows:

 java Addressables 

You should observe the following output:

 100 - Main Street - Town A 200 - Waterfront Drive - Town B 300 - 10th Ave - Town C 

Nested interfaces with static methods (static method interfaces)

Many developers believe that nesting a class in an interface violates object-oriented programming and the purpose for an interface. However, it's good to know about this capability because you might encounter it when maintaining someone else's code. Furthermore, now that interfaces have evolved to include default and static methods, you might encounter additional reasons to nest a class in an interface. As an example, here is a local class nested within a static method interface:

 interface I { static void m() { class C { } } } 

Conclusion

I've presented three common ways to use nesting techniques with Java classes and interfaces, and also demonstrated a controversial technique of nesting interfaces with static methods. See the complete Java 101 tutorial to learn more about nesting with static classes and inner classes in Java.

Esta historia, "Anidamiento con interfaces Java" fue publicada originalmente por JavaWorld.