Pergunta

É possível criar uma classe interna dentro de uma interface? Se for possível, por que queremos criar uma classe interna assim desde nós não estamos indo para criar quaisquer objetos de interface?

Será que estas classes internas ajuda em qualquer processo de desenvolvimento?

Foi útil?

Solução

Sim, você pode criar tanto uma classe aninhada ou uma classe interna dentro de uma interface Java (note que ao contrário da crença popular, não há tal coisa como um " classe interna estática ": isso simplesmente não faz sentido, não há nada de 'interior' e não 'outter' classe quando uma classe aninhada é estático, por isso não pode ser 'interna estática')

.

De qualquer forma, o seguinte compila bem:

public interface A {
    class B {
    }
}

Eu já vi isso usado para colocar algum tipo de "verificador de contrato" diretamente na definição de interface (bem, na classe aninhada na interface, que pode ter métodos estáticos, ao contrário da própria interface, que não pode ). Olhando assim, se bem me lembro.

public interface A {
    static class B {
        public static boolean verifyState( A a ) {
            return (true if object implementing class A looks to be in a valid state)
        }
    }
}

Note que não estou comentando sobre a utilidade de tal coisa uma, estou simplesmente respondendo à sua pergunta: isso pode ser feito e este é um tipo de uso que eu vi feito dele

.

Agora, eu não vou comentar sobre a utilidade de tal construção e do que eu vi:. Eu já vi isso, mas não é uma construção muito comum

200KLOC codebase aqui onde isso acontece exatamente o tempo zero (mas, em seguida, temos um monte de outras coisas que consideramos más práticas que acontecem exatamente zero vez também que outras pessoas acham tão perfeitamente normal ...).

Outras dicas

Sim, nós podemos ter aulas dentro de interfaces. Um exemplo de uso poderia ser

public interface Input
{
    public static class KeyEvent {
         public static final int KEY_DOWN = 0;
         public static final int KEY_UP = 1;
         public int type;
         public int keyCode;
         public char keyChar;
    }
    public static class TouchEvent {
         public static final int TOUCH_DOWN = 0;
         public static final int TOUCH_UP = 1;
         public static final int TOUCH_DRAGGED = 2;
         public int type;
         public int x, y;
         public int pointer;
    }
    public boolean isKeyPressed(int keyCode);
    public boolean isTouchDown(int pointer);
    public int getTouchX(int pointer);
    public int getTouchY(int pointer);
    public float getAccelX();
    public float getAccelY();
    public float getAccelZ();
    public List<KeyEvent> getKeyEvents();
    public List<TouchEvent> getTouchEvents();
}

Aqui, o código tem duas classes aninhadas que são para encapsular informações sobre objetos de eventos que são posteriormente usadas em definições de métodos como getKeyEvents (). Tê-los dentro da interface de entrada melhora a coesão.

A utilização válida, IMHO, é definir objetos que são recebidos ou devolvidos pelos métodos de interface que encerram. Tipicamente dados segurando estruturas. Dessa forma, se o objeto só é usado para essa interface, você tem coisas de uma maneira mais coesa.

Por exemplo:

interface UserChecker {
   Ticket validateUser(Credentials credentials);

   class Credentials {
      // user and password
   }

   class Ticket {
      // some obscure implementation
   }
}

Mas de qualquer forma ... é apenas uma questão de gosto.

Citação da Java 7 especificação :

interfaces podem conter declarações de tipo membro (§8.5).

A declaração de tipo de membro em uma interface é implicitamente estático e público. É permitido redundante especificar um ou ambos destes modificadores.

Não é possível declarar classes não-estáticos dentro de uma interface Java, o que faz sentido para mim.

Um caso de uso interessante é fornecer uma espécie de implementação padrão para métodos de interface através de uma classe interna, como descrito aqui: https: // stackoverflow.com/a/3442218/454667 (para superar o problema da classe-herança simples).

É certamente possível, e um caso em que eu achei útil é quando uma interface tem que lançar exceções personalizadas. Você a manter as exceções com sua interface associada, que eu acho que muitas vezes é mais puro do que sujando sua árvore fonte com montes de arquivos de exceção triviais.

interface MyInterface {

   public static class MyInterfaceException extends Exception {
   }

   void doSomething() throws MyInterfaceException;
}

Sim, é possível ter definições de classe estáticos dentro de uma interface, mas talvez o aspecto mais útil desse recurso é quando utilizar tipos de enum (que são tipo especial de classes estáticas). Por exemplo, você pode ter algo como isto:

public interface User {
    public enum Role {
        ADMIN("administrator"),
        EDITOR("editor"),
        VANILLA("regular user");

        private String description;

        private Role(String description) {
            this.description = description;
        }

        public String getDescription() {
            return description;
        }
    }

    public String getName();
    public void setName(String name);
    public Role getRole();
    public void setRole(Role role);
    ...
}

O que @Bachi menciona é semelhante ao traços em Scala e são realmente implementadas usando uma classe aninhada dentro de uma interface. Isto pode ser simulado em Java. Veja também java traços ou mixins padrão?

Talvez quando você quer construções mais complexas como alguns comportamentos diferentes de implementação, considere:

public interface A {
    public void foo();

    public static class B implements A {
        @Override
        public void foo() {
            System.out.println("B foo");
        }
    }
}

Esta é a sua interface e este será o implementee:

public class C implements A {
    @Override
    public void foo() {
        A.B b = new A.B();
        b.foo(); 
    }

    public static void main(String[] strings) {
        C c = new C();
        c.foo();
    }
}

Pode fornecer algumas implementações estáticas, mas não que ser confuso, eu não sei.

Eu encontrei um uso fir este tipo de construção.

  1. Você pode usar esta construção a define e agrupar todas as constantes finais estáticos.
  2. Desde que, é uma interface que você pode implementar isso em uma classe.

Você tem acesso a todas as constantes agrupadas; nome da classe atua como um namespace neste caso.

Você também pode criar "auxiliar" classes estáticas para a funcionalidade comum para os objetos que implementar essa interface:

public interface A {
    static class Helper {
        public static void commonlyUsedMethod( A a ) {
           ...
        }
    }
}

Eu estou precisando de um agora. Eu tenho uma interface onde seria conveniente para retornar uma única classe de vários dos seus métodos. Esta classe só faz sentido como um recipiente para as respostas dos métodos desta interface.

Por isso, seria conveniente ter uma definição de classe aninhada estática, que está associado apenas com esta interface, uma vez que esta interface deve ser o único lugar onde essa classe resultados recipiente é já criado.

Por exemplo traços (smth como interface com métodos implementados) em Groovy. Eles são compilados para uma interface que contém classe interna, onde todos os métodos são implementados.

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