Imbrication avec des interfaces Java

Si vous avez lu mon didacticiel Java 101 présentant les classes statiques et les classes internes, vous devez être familiarisé avec les bases de l'utilisation des classes imbriquées dans le code Java. Dans cette astuce Java, vous apprendrez trois façons courantes d'utiliser les techniques d'imbrication avec les interfaces Java. Je vais également montrer brièvement les interfaces d'imbrication avec des méthodes statiques, également appelées interfaces de méthode statique.

En savoir plus sur les interfaces Java

Pour une introduction aux interfaces Java, y compris la différence entre les classes et les interfaces, consultez mon tutoriel Java 101 Travailler avec des interfaces en Java.

Imbrication d'interfaces dans les classes

Java vous permet de déclarer des interfaces à l'intérieur des classes. Une fois déclarée, une interface est automatiquement un membre statique de la classe. Il n'est pas nécessaire de déclarer l'interface avec le staticmot - clé. Prenons l'exemple suivant:

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

EnclosedInterface1et EnclosedInterface2sont des interfaces membres statiques . Il n'y a pas d'équivalent aux classes locales car les interfaces ne peuvent pas être déclarées en blocs. Cependant, les interfaces peuvent être utilisées dans des contextes de classes anonymes.

Les interfaces imbriquées ne sont généralement pas accessibles au-delà de leurs classes englobantes. Sinon, vous pouvez les déclarer comme interfaces de niveau supérieur . Au lieu de cela, ils sont accessibles depuis l'intérieur de leurs classes englobantes, comme illustré ici:

 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() { }; } } 

Notez que la classe membre statique EnclosedClass1, la classe membre non statique EnclosedClass2et la classe locale EnclosedClass3implémentent les deux interfaces imbriquées. Cependant, une seule interface peut être implémentée dans un contexte de classe anonyme. (Voir Classes statiques et classes internes en Java pour plus d'informations sur les classes anonymes.)

Classes avec des interfaces imbriquées dans java.net

La bibliothèque de classes standard de Java comprend des classes avec des interfaces imbriquées. Par exemple, InetAddress(dans le java.netpackage), qui représente une adresse de protocole Internet, déclare une Addressesinterface privée implémentée par des classes membres privées CachedAddresseset NameServiceAddressesstatiques. Il déclare également une NameServiceinterface privée implémentée par des classes membres privées PlatformNameServiceet HostsFileNameServicestatiques.

Imbrication d'interfaces dans les interfaces

Java vous permet également de déclarer des interfaces à l'intérieur des interfaces. Dans ce cas, une interface imbriquée est un membre statique de son interface englobante, et encore une fois le staticmot-clé est redondant. En outre, l'interface imbriquée est implicitement publique. Voici un exemple:

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

Vous accédez à une interface incluse en préfixant son nom avec le nom de l'interface englobante et l'opérateur d'accès aux membres. Par exemple, spécifiez EnclosingInterface.EnclosedInterface1pour accéder EnclosedInterface1.

Interfaces imbriquées dans Java Collections Framework

Le Java Collections Framework fournit un aperçu de l'utilité de l'imbrication d'une interface dans une autre. Considérez l' java.util.Mapinterface, qui décrit une carte (une collection de paires clé-valeur). L' Mapinterface résume ce que signifie être une carte. Classes telles que HashMapet java.util.TreeMapimplémentation Map, décrivant différents types d'implémentations de carte

Mapdéclare Entrycomme l'un de ses membres. Entryest une interface imbriquée qui décrit une paire clé-valeur. L' Entryinterface est déclarée en Mapraison de la relation étroite entre les deux interfaces - chaque entrée doit appartenir à une carte. Entryest implémenté par la java.util.AbstractMapclasse SimpleEntryet SimpleImmutableEntryles classes membres statiques. Vous ignorerez généralement ces classes membres statiques et interagirez avec à la Map.Entryplace.

Imbrication de classes dans les interfaces

L'une des fonctionnalités les plus étranges du langage Java est la possibilité d'imbriquer une classe dans une interface. Comme pour une interface imbriquée, la classe imbriquée est implicitement publique et statique. Voici un exemple:

 interface EnclosingInterface { class EnclosedClass { } } 

Malgré son étrangeté, être capable d'imbriquer une classe dans une interface peut être utile, en particulier lorsqu'il existe une relation étroite entre l'interface englobante et la classe incluse. La capture de cette relation améliore la lisibilité du code source. Dans les cas où la classe et l'interface portent le même nom, l'imbrication peut également vous aider à éviter un conflit de nom entre les deux.

Exemple: l'interface adressable englobe la classe d'adresse

Supposons que vous souhaitiez modéliser des entités adressables telles que des lettres, des cartes postales et des colis. Chaque entité sera décrite par sa propre classe, mais elles partagent toutes le point commun d'être adressables à une destination. Chaque classe peut être conçue avec des champs d'adresse en double, ou vous pouvez résumer ces détails dans une superclasse commune. Vous pouvez également utiliser l' Addressableinterface du Listing 1 .

Listing 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(); } 

L' Addressableinterface décrit une entité adressable comme contenant une adresse. Cette adresse est décrite par la Addressclasse imbriquée . La getAddress()méthode est implémentée par n'importe quelle classe implémentée Addressable.

Le listing 2 présente le code source à une Letterclasse qui implémente Addressable.

Listing 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; } } 

Letterstocke un seul addresschamp de type Addressable.Address. Cette classe imbriquée est instanciée par Letterle constructeur de. La getAddress()méthode implémentée renvoie cet objet.

Considérons maintenant ce qui se passe lorsque l' on ajoute Postcardet Parcelcours à l' Addressablesapplication. Listing 3 présente le code source à une Addressablesapplication, ce qui démontre les Postcard, Parcelet les Lettertypes.

Listing 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.

Cette histoire, "Nesting with Java interfaces" a été initialement publiée par JavaWorld.