Подтвердить что ты не робот

Какое преимущество наличия открытых статических внутренних классов интерфейса/класса?

Я заметил следующий шаблон кода при просмотре некоторых источников сторонних библиотек проекта:

public interface MyInterface {
    public static class MyClass1 implements MyInterface { ... }
    public static class MyClass2 implements MyInterface { ... }
    public static class MyClass3 implements MyInterface { ... }
}

Или этот:

public class MyBaseClass {
    public static class MyClass1 extends MyBaseClass { ... }
    public static class MyClass2 extends MyBaseClass { ... }
    public static class MyClass3 extends MyBaseClass { ... }
}

Примеры реальной жизни:

  • SwingX: org.jdesktop.swingx.decorator.HighlightPredicate (Источник)
  • Вещество: org.pushingpixels.substance.api.renderers.SubstanceDefaultTableCellRenderer (Источник)

В чем преимущество наличия такой структуры кода?

Моя первая мысль была "агрегация", но то же самое можно было сделать, используя простые старые пакеты. Итак, когда/почему лучше использовать общедоступные внутренние классы вместо пакета?

4b9b3361

Ответ 1

Я думаю, что это связано с агрегацией, возможно, они также не стоят того, чтобы создать класс верхнего уровня. Я делаю это иногда, если что-то мало для создания пакета (чтобы отделить их от других), но соответствующие классы должны использоваться только в контексте класса верхнего уровня. По-моему, это дизайнерское решение.

Рисунок декоратора может быть хорошим примером, их можно применять в классе верхнего уровня, но, возможно, так просто, что они не стоят того, чтобы быть также на высшем уровне. Вы можете легко показать право собственности, используя их как внутренние классы.

Это не то, что видно на первый взгляд с пакетами. Вы непосредственно видите зависимый класс/интерфейс.

Кроме того, можно получить доступ к закрытым полям класса, это может быть полезно и более мелкозернистым, чем закрытая область пакета.

Ответ 2

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

Это имеет смысл только в том случае, если интерфейс прост (при этом внутренние классы реализации небольшие), их не так уж много, и большинство интерфейсных клиентов им действительно нужны. В противном случае они загромождают исходный файл, что затрудняет понимание.

Ответ 3

Что касается классов и их внутренних классов (не относится к интерфейсам), то одно отличие состоит в том, что внутренние классы могут использовать частные члены внешнего класса, что не так, если они были "братья и сестры" (отдельные классы верхнего уровня).

Пример:

public class MyBaseClass {

    private static String staticField = "outer";

    public static class MyClass1 extends MyBaseClass { 

      public MyClass1() {
          MyBaseClass.staticField = "inner1";
      }

    }
}

Это не сработает, если вы переместили MyClass из внешнего класса.

Ответ 4

Внутренний интерфейс должен быть статичным для доступа. Интерфейс не связан с экземплярами класса, но с самим классом, поэтому он будет доступен с помощью Foo.Bar, например.

Ответ 5

Выполнение этого способа может сэкономить вам дополнительные файлы исходного кода и дать классу хорошее иерархическое имя, т.е. org.foo.bar.XY.Default вместо org.foo.bar.DefaultXY

Ответ 6

Я думаю, что причина публичного статического внутреннего класса - дополнительный инструмент или утилита для "базового" класса.

Ответ 7

Когда я спросил своего учителя об этом много лет назад, он ответил, что таким образом вы можете открыть совершенно другой интерфейс для одного и того же объекта. Предположим, что у вас

public class MyBaseClass {
    public static class MyClass1 {
       public int myClassMethod1() {...}
       public int myClassMethod2() {...}
    }
    ...
    public void myBaseMethod1() {...}
    public void myBaseMethod2() {...}
}

Поскольку экземпляры MyClass1 имеют доступ к внутренним компонентам MyBaseClass, вы можете выявить то же внутреннее поведение, что и экземпляр MyClass1, или как экземпляр MyBaseClass по мере необходимости, даже если определенные методы в обоих классах совершенно разные.

Мне никогда не приходилось использовать это, но действительно интересно.