Pergunta

Qual seria o lado prático da capacidade de definir uma classe dentro de uma interface em Java:

interface IFoo
{
    class Bar
    {
        void foobar ()
        {
            System.out.println("foobaring...");
        }
    }
}
Foi útil?

Solução

Não consigo pensar em outro uso do que aqueles ligados por Eric P:. Definição de uma implementação padrão / não-op da interface

./ alex

interface IEmployee
{

    void workHard ();  
    void procrastinate ();

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

}

No entanto, outra amostra - implementação de Null Objecto Padrão :

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);
...

Outras dicas

este página explica um exemplo muito bem. Você poderia usá-lo para ligar fortemente um determinado tipo para uma interface.

Shamelessly arrancou a partir do link acima:

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

Na interface acima você está ligando o tipo de papel fortemente para a interface do empregado (employee.Role).

Um uso (para melhor ou pior) seria como uma solução para o fato de que Java não suporta métodos estáticos em interfaces.

interface Foo {
    int[] getData();

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

Então você chamá-lo com:

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

Eu posso dizer sem hesitação que eu nunca fiz isso. Eu não posso pensar em uma razão por que você quer. Classes aninhadas dentro de classes? Claro, muitas razões para fazer isso. Nos casos em que tendem a considerar essas classes internas para ser um detalhe de implementação. Obviamente, uma interface não tem detalhes de implementação.

Um lugar este idioma é muito usado está em XMLBeans . O objetivo desse projeto é levar um esquema XML e gerar um conjunto de classes Java que você pode usar bidirectionally ao trabalho com documentos XML correspondentes ao esquema. Assim, permite-lhe analisar XML em grãos de XML ou criar o feijão XML e saída para xml.

Em geral, a maioria dos tipos de esquema XML são mapeados para uma interface Java. Essa interface tem dentro de si uma fábrica que é usado para gerar instâncias dessa interface na implementação padrão:

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

Quando encontrei pela primeira vez esta parecia errado para ligar tudo isto lamaçal implementação para a definição de interface. No entanto, eu realmente cresci a gostar dele como ele deixe tudo ficar definido em termos de interfaces, mas tem uma maneira uniforme para obter instâncias da interface (em oposição a ter uma outra classe externo fábrica / construtor).

Eu o peguei para classes onde isso fez sentido (particularmente aqueles onde eu tinha uma grande quantidade de controle sobre a interface / impls) e achei a ser bastante limpo.

Eu acho que você poderia definir uma classe que é usado como o tipo de retorno ou tipo de parâmetro para os métodos de dentro da interface. não parece particularmente útil. Você pode muito bem definir a classe separadamente. A única possível vantagem é que ele declara a classe como "pertencente" à interface em algum sentido.

O Google Web Toolkit usa essas classes para a interface de ligação 'normal' para a interface chamada assíncrona:

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

Com uma classe estática dentro de uma interface que você tem a possibilidade de encurtar um fragmento de programação comum: Verificando se um objeto é uma instância de uma interface, e se assim chamar um método desta interface. Veja este exemplo:

public interface Printable {
    void print();

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

Agora, em vez de fazer isso:

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

Você pode escrever:

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

Fazendo isso parece ter "decisão de projeto Bad" escrito tudo sobre ele.

Gostaria de exortar cuidado sempre que ele parece ser uma boa idéia para criar uma classe aninhada não-privados. Você está quase certamente melhor fora de ir direto para uma classe externa. Mas se você estiver indo para criar uma classe aninhada pública, não parece mais estranho para colocá-lo em uma interface de uma classe. A abstração da classe externa não está necessariamente relacionado com a abstração de uma classe aninhada.

Esta abordagem pode ser usada para definir muitas classes no mesmo arquivo. Isso tem funcionado bem para mim no passado onde eu tenho muitas implementações simples de uma interface. No entanto, se eu fosse fazer isso de novo, eu iria usar um enum que implementa uma interface que teria sido uma solução mais elegante.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top