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

Практическая сторона способности определять класс внутри интерфейса в Java?

Какова была бы практическая сторона способности определять класс внутри интерфейса в Java:

interface IFoo
{
    class Bar
    {
        void foobar ()
        {
            System.out.println("foobaring...");
        }
    }
}
4b9b3361

Ответ 1

Я могу придумать другое использование, чем те, которые связаны с Eric P: определение реализации интерфейса по умолчанию /no -op.

./Алекс

interface IEmployee
{

    void workHard ();  
    void procrastinate ();

    class DefaultEmployee implements IEmployee 
    {
        void workHard () { procrastinate(); };
        void procrastinate () {};
    }

}

Еще один пример - реализация Нулевой шаблон объекта:

interface IFoo
{
    void doFoo();
    IFoo NULL_FOO = new NullFoo();

    final class NullFoo implements IFoo
    {
        public void doFoo () {};
        private NullFoo ()  {};
    }
}


...
IFoo foo = IFoo.NULL_FOO;
...
bar.addFooListener (foo);
...

Ответ 2

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

Бесстыдно срывается с вышеуказанной ссылки:

interface employee{
    class Role{
          public String rolename;
          public int roleId;
     }
    Role getRole();
    // other methods
}

В вышеприведенном интерфейсе вы сильно привязываете тип роли к интерфейсу сотрудника (employee.Role).

Ответ 3

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

interface Foo {
    int[] getData();

    class _ {
        static int sum(Foo foo) {
            int sum = 0;
            for(int i: foo.getData()) {
                sum += i;
            }
            return sum;
        }
    }
}

Затем вы назовете его:

int sum = Foo._.sum(myFoo);

Ответ 4

Я могу без колебаний сказать, что никогда этого не делал. Я не могу думать о причине, по которой вы тоже. Классы, вложенные в классы? Конечно, много причин для этого. В этих случаях я склонен рассматривать эти внутренние классы как детали реализации. Очевидно, что интерфейс не имеет деталей реализации.

Ответ 5

Одно место, в котором эта идиома используется, находится в XMLBeans. Цель этого проекта - взять XML-схему и создать набор классов Java, которые вы можете использовать в двунаправленном режиме для работы с документами XML, соответствующими схеме. Таким образом, он позволяет анализировать XML в xml beans или создавать xml beans и выводить на xml.

В общем, большинство типов схем xml сопоставляются с интерфейсом Java. В этом интерфейсе есть Factory, который используется для генерации экземпляров этого интерфейса в реализации по умолчанию:

public interface Foo extends XmlObject {
  public boolean getBar();
  public boolean isSetBar();
  public void setBar(boolean bar);

  public static final SchemaType type = ...

  public static final class Factory {
    public static Foo newInstance() {
      return (Foo)XmlBeans.getContextTypeLoader().newInstance(Foo.type, null);
    }

    // other factory and parsing methods
  }
} 

Когда я впервые столкнулся с этим, было бы неправильно связывать всю эту реализацию gunk с определением интерфейса. Тем не менее, мне на самом деле понравилось, так как он позволяет всем определять в терминах интерфейсов, но имеет единый способ получить экземпляры интерфейса (в отличие от другого внешнего класса Factory/builder).

Я поднял его для классов, где это имело смысл (особенно те, где я имел большой контроль над интерфейсом/имплантами) и нашел, что он довольно чист.

Ответ 6

Я думаю, вы могли бы определить класс, который используется как тип возвращаемого значения или тип параметра для методов в интерфейсе. Не кажется особенно полезным. Вы можете просто определить класс отдельно. Единственное возможное преимущество заключается в том, что он объявляет класс как "принадлежащий" интерфейсу в некотором смысле.

Ответ 7

Google Web Toolkit использует такие классы для привязки "нормального" интерфейса к асинхронному интерфейсу вызовов:

public interface LoginService extends RemoteService {

    /**
     * Utility/Convenience class.
     * Use LoginService.App.getInstance() to access static instance of LoginServiceAsync
     */
    class App {

        public static synchronized LoginServiceAsync getInstance() {
            ...
        }
    }
}

Ответ 8

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

public interface Printable {
    void print();

    public static class Caller {
        public static void print(Object mightBePrintable) {
            if (mightBePrintable instanceof Printable) {
                ((Printable) mightBePrintable).print();
            }
        }
    }
}

Теперь вместо этого:

void genericPrintMethod(Object obj) {
    if (obj instanceof Printable) {
        ((Printable) obj).print();
    }
}

Вы можете написать:

void genericPrintMethod(Object obj) {
   Printable.Caller.print(obj);
}

Ответ 9

У этого, кажется, есть "плохое дизайнерское решение", написанное во всем этом.

Ответ 10

Я бы настоятельно рекомендовал всякий раз, когда кажется хорошей идеей создать неединичный вложенный класс. Вам почти наверняка лучше идти прямо на внешний класс. Но если вы собираетесь создать публичный вложенный класс, не представляется более странным помещать его в интерфейс, чем класс. Абстрактность внешнего класса не обязательно связана с абстрактностью вложенного класса.

Ответ 11

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