Влагане с Java интерфейси

Ако сте прочели моя урок за Java 101, представящ статични класове и вътрешни класове, трябва да сте запознати с основите на работата с вложени класове в Java кода. В този съвет на Java ще научите три често срещани начина за използване на техники за влагане с Java интерфейси. Също така ще демонстрирам накратко интерфейси за влагане със статични методи, известни също като интерфейси за статични методи.

Повече за Java интерфейсите

За въведение в интерфейсите на Java, включително разликата между класове и интерфейси, вижте моя урок за Java 101 Работа с интерфейси в Java.

Влагане на интерфейси в класове

Java ви позволява да декларирате интерфейси вътре в класовете. Веднъж деклариран, интерфейсът автоматично е статичен член на класа. Не е необходимо да декларирате интерфейса с staticключовата дума. Обмислете следния пример:

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

EnclosedInterface1и EnclosedInterface2са статични интерфейси на членове . Няма еквивалент на локални класове, защото интерфейсите не могат да бъдат декларирани в блокове. Интерфейсите обаче могат да се използват в контексти на анонимни класове.

Вложените интерфейси обикновено не са достъпни отвъд заграждащите ги класове. В противен случай можете да ги декларирате като интерфейси от най-високо ниво . Вместо това те са достъпни от вътрешните им класове, както е показано тук:

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

Обърнете внимание, че статичният клас член EnclosedClass1, нестатичният член член EnclosedClass2и локалният клас EnclosedClass3изпълняват и двата вложени интерфейса. Въпреки това, само един интерфейс може да бъде реализиран в контекст на анонимен клас. (Вижте статични класове и вътрешни класове в Java за повече информация относно анонимните класове.)

Класове с вложени интерфейси в java.net

Стандартната библиотека на класове на Java включва класове с вложени интерфейси. Например InetAddressjava.netпакета), който представлява адрес на интернет протокол, декларира частен Addressesинтерфейс, който е реализиран от частни CachedAddressesи NameServiceAddressesстатични класове членове. Той също така декларира частен NameServiceинтерфейс, който е реализиран от частни PlatformNameServiceи HostsFileNameServiceстатични класове членове.

Влагане на интерфейси в интерфейси

Java също ви позволява да декларирате интерфейси вътре в интерфейсите. В този случай вложен интерфейс е статичен член на заграждащия го интерфейс и отново staticключовата дума е излишна. Също така, вложеният интерфейс е имплицитно публичен. Ето пример:

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

Имате достъп до затворен интерфейс, като добавяте името му пред името на заграждащия интерфейс и оператора за достъп на членове. Например посочете EnclosingInterface.EnclosedInterface1за достъп EnclosedInterface1.

Вложени интерфейси в Java Collections Framework

Рамката на Java Collections дава представа за полезността на влагането на един интерфейс в друг. Помислете за java.util.Mapинтерфейса, който описва карта (колекция от двойки ключ-стойност). В Mapинтерфейса резюмета какво означава да си на карта. Класове като HashMapи java.util.TreeMapизпълнение Map, описващи различни видове внедряване на карти.

Mapдекларира Entryкато един от своите членове. Entryе вложен интерфейс, който описва двойка ключ-стойност. В Entryинтерфейса е обявен в Mapпоради тясната връзка между двата интерфейса - всеки запис трябва да принадлежи на картата. Entryсе реализира от java.util.AbstractMapкласовете SimpleEntryи SimpleImmutableEntryстатичните членове на класа. Обикновено ще игнорирате тези статични класове членове и ще взаимодействате с тях Map.Entry.

Класове за влагане в интерфейси

Една от по-непознатите езикови характеристики на Java е възможността за влагане на клас в интерфейс. Както при вложения интерфейс, вложеният клас е имплицитно публичен и статичен. Ето пример:

 interface EnclosingInterface { class EnclosedClass { } } 

Въпреки неговата странност, възможността за влагане на клас в интерфейса може да бъде полезна, особено когато има тясна връзка между заграждащия интерфейс и затворения клас. Заснемането на тази връзка подобрява четливостта на изходния код. В случаите, когато класът и интерфейсът носят едно и също име, влагането също може да ви помогне да избегнете конфликт на имена между двете.

Пример: Адресируемият интерфейс затваря адресния клас

Да предположим, че искате да моделирате адресируеми обекти като писма, пощенски картички и колети. Всеки обект ще бъде описан от свой собствен клас, но всички те споделят общото, че могат да бъдат адресирани до някаква дестинация. Всеки клас може да бъде проектиран с дублирани полета за адрес или може да абстрахирате тези подробности в общ суперклас. Като алтернатива можете да използвате Addressableинтерфейса на Листинг 1 .

Листинг 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(); } 

В Addressableинтерфейса описва адресируема единица като съдържаща адрес. Този адрес е описан от вложения Addressклас. В getAddress()метода се осъществява от каквото и клас изпълнява Addressable.

Листинг 2 представя изходния код на Letterклас, който изпълнява Addressable.

Листинг 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; } } 

Letterсъхранява едно addressполе от тип Addressable.Address. Този вложен клас е създаден от Letterконструктора на '. Реализираният getAddress()метод връща този обект.

Сега помислете какво се случва, когато добавяме Postcardи Parcelкласове към Addressablesприложението. Обява 3 съдържа изходния код на Addressablesприложение, което показва Postcard, Parcelи Letterвидовете.

Листинг 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.

Тази история „Влагане с Java интерфейси“ първоначално е публикувана от JavaWorld.