Философия Java

Вложенные интерфейсы


[39]Интерфейсы могут быть вложены внутрь классов и других интерфейсов. Такая возможность выявляет несколько очень интересных возможностей:

//: c08:NestingInterfaces.java

class A { interface B { void f(); } public class BImp implements B { public void f() {} } private class BImp2 implements B { public void f() {} } public interface C { void f(); } class CImp implements C { public void f() {} } private class CImp2 implements C { public void f() {} } private interface D { void f(); } private class DImp implements D { public void f() {} } public class DImp2 implements D { public void f() {} } public D getD() { return new DImp2(); } private D dRef; public void receiveD(D d) { dRef = d; dRef.f(); } }

interface E { interface G { void f(); } // избыточный "public":

public interface H { void f(); } void g(); // Не может быть private внутри интерфейса:

//! private interface I {}

}

public class NestingInterfaces { public class BImp implements A.B { public void f() {} } class CImp implements A.C { public void f() {} } // Не может быть реализован private interface без

// внутреннего определения класса:

//! class DImp implements A.D {

//! public void f() {}

//! }

class EImp implements E { public void g() {} } class EGImp implements E.G { public void f() {} } class EImp2 implements E { public void g() {} class EG implements E.G { public void f() {} } } public static void main(String[] args) { A a = new A(); // Нет доступа A.D:

//! A.D ad = a.getD();

// Ничего не возвращается, кроме A.D:

//! A.DImp2 di2 = a.getD();

// Нельзя получить доступ к участнику интерфейса:

//! a.getD().f();

// Только другой A может что-то делать с getD():

A a2 = new A(); a2.receiveD(a.getD()); } } ///:~

Синтаксис внутреннего интерфейса внутри класса очевиден и похож на не внутренние интерфейсы, которые могут быть public или friendly. Вы так же видите, что оба внутренних интерфейса public и friendly могут быть реализованы как public, friendly и private внутренние классы.

С этой новой особенностью интерфейсы могут так же быть private, как видно из A.D (тот же самый синтаксис используется для внутренний интерфейсов и для внутренних классов). Что же хорошего в private внутреннем интерфейсе? Как Вы можете догадаться, он может быть реализован только как private внутренний класс, как, например в DImp, но в A.DImp2 видно, что он так же может быть реализован и как public класс. Но все равно, A.DImp2 может быть использован только как сам. Однако не следует пропустить упоминание о том, что реализация private интерфейса это всего лишь путь для принудительного определения методов в этом интерфейсе, без добавления любой информации о типе (это так и есть, без возможности любого приведения к базовому типу).


Метод getD( ) вызывает дальнейшие затруднения связанные с private интерфейсом: это public метод, который возвращает ссылку на private интерфейс. И что Вы будете делать с этим возвращенным значением? В main( ), Вы можете видеть несколько провалившихся попыток что-либо поделать с ним. Единственная вещь способная работать с ним - это может быть объект имеющий на него права, в нашем случае другой объект A, посредством метода received( ).

Интерфейс E показывает, что интерфейсы могут быть вложены друг в друга. Но все равно, правила насчет интерфейсов следующие, все элементы интерфейса должны быть public, но в случае внутреннего интерфейса внутри другого интерфейса они все и так становятся public автоматически и не могут быть сделаны private.

NestingInterfaces показывает различные пути реализации внутренних интерфейсов. В частности заметьте, что когда Вы реализуете интерфейс, вам не нужно так же реализовывать внутренние интерфейсы, находящиеся в нем. Так же, private интерфейсы не могут быть реализованы снаружи класса, в котором они определены.


Содержание раздела