Quando Interface é ncessário?

Bom dia Pessoal,

Estou com a seguinte dúvida em relação ao uso de Interfaces em Java.
Eu entendo que uma interface é como se fosse um contrato, em que todas as classes que implementá-la, terá que implementar seus métodos, assim todos as classes terão os mesmos métodos publicos, ou seja, a mesma interface.

Porém minha dúvida é em relação para quando de fato eu tenho que utilizar uma interface ou não.

Olhando os Mocks para JUnit (como por exemplo o EasyMock), ele diz para fazer mock em cima de interfaces (embora exista um projeto para mock em cima de classe concreta), mas se for para fazer mock apenas em interfaces, praticamente TODAS classes concretas do meu projeto terá que estar associada a alguma interface, e ao meu ver, isso é um desperdício de recursos e produtividade.

Então pesso ajuda dos experientes em arquitetura em deixar claro, quando realmente devemos usar Interface, e se realmente devemos usar em todos os objetos concretos?

Agradeço desde já

Um ponto importante das interfaces é que, usando polimorfismo, você pode evitar dependências e reduzir o acoplamento.

Exemplo: Veja o CharSequence, presente na biblioteca do Java.

Nao sou experiente em arquitetura, mas vou te passar o que eu entendo de qdo usar interface…

Suponhamos que vc tenha varias telas de cadastro no seu sistema… vc quer criar uma barra de botões única no seu frame Principal, e quer que todas essas telas suas forneçam implementações dos métodos “salvarRegistro()” e “novoRegistro()”…

Pra usá-los de maneira polimórfica, vc pdoeria criar um formulario, digamos, AbstractForm e assinalar esses metodos como abstract, e entao nas classes herdeiras vc “sobrecarregar” esses métodos.

Mas isso faz com que todas essas telas OBRIGATORIAMENTE herdem de AbstractForm. E só pode haver uma herança, e vc ja queimou o recurso da herança ( que é muito mais do que herdar métodos para serem sobrescritos ).

Ao invés disso, vc cria uma interface chamada InterfaceCadastro, que contem as assintaturas desses métodos, e todas telas que IMPLEMENTAREM essa interface estarão obrigadas a fornecer implementações concretas pra esses métodos. E todas essas telas podem ser tratadas como objetos do tipo InterfaceCadastro. Com isso, suas telas ficam livres pra herdar outra coisa. Ex: JInternalFrame.

Nao sou experiente em arquitetura, mas vou te passar o que eu entendo de qdo usar interface…

Suponhamos que vc tenha varias telas de cadastro no seu sistema… vc quer criar uma barra de botões única no seu frame Principal, e quer que todas essas telas suas forneçam implementações dos métodos “salvarRegistro()” e “novoRegistro()”…

Pra usá-los de maneira polimórfica, vc pdoeria criar um formulario, digamos, AbstractForm e assinalar esses metodos como abstract, e entao nas classes herdeiras vc “sobrecarregar” esses métodos.

Mas isso faz com que todas essas telas OBRIGATORIAMENTE herdem de AbstractForm. E só pode haver uma herança, e vc ja queimou o recurso da herança ( que é muito mais do que herdar métodos para serem sobrescritos ).

Ao invés disso, vc cria uma interface chamada InterfaceCadastro, que contem as assintaturas desses métodos, e todas telas que IMPLEMENTAREM essa interface estarão obrigadas a fornecer implementações concretas pra esses métodos. E todas essas telas podem ser tratadas como objetos do tipo InterfaceCadastro. Com isso, suas telas ficam livres pra herdar outra coisa. Ex: JInternalFrame.

Olá Alex…

Bem, como vc disse, uma interface é uma especie de contrato. Com ela você define quais operações você vai querer utilizar em uma classe.

Com isso você pode permitir que sua aplicação use objetos de classes diferentes que, pelo contrato da interface, disponibilizam pra você as mesmas operações. Contudo, cada objeto pode implementar uma operação de uma maneira diferente.

Um bom exemplo são (classes do java): java.util.List, java.util.ArrayList e java.util.LinkedList
Tanto o ArrayList como o LinkedList são usados para armazenar os itens em sequencia, mas um armazena os itens em Array e o ooutro em uma lista ligada. isso implica que várias operações - como um add e remove, por exemplo - tenham implementações distintas mas, por força de contrato, atendem pelo mesmo nome.

A interface é extremamente útil quando você tem esses casos. Mas ela tbm é útil quando você quer que um mesmo objeto possa se comportar de várias maneiras diferentes. Por exemplo:
Você possui duas interfaces: “Bola” e outra "Tampa"
Na interface “Bola” você tem definidas as ações que podem ser executadas com a bola - “quicar” ou “pular” por exemplo.
Na interface “Tampa” você tem definidas as ações que podem ser executadas com uma tampa - “tampar” - por exemplo.

Agora, imagine que você tem uma classe “TampaDeGarrafa” que implementa as duas interfaces - “Bola” e “Tampa”. E, dessa forma, um objeto da classe “TampaDeGarrafa” pode ser usado como tampa e tbm pode ser sado como bola… :wink:

Acredito que você ja usou uma tampinha de garrafa como bola alguma vez na sua vida, certo? E com certeza, você já havia usado a mesma tampa em alguma garrafa antes de começar a chutá-la…

Bem… espero tê-lo ajudado.

Olá Alex…

Bem, como vc disse, uma interface é uma especie de contrato. Com ela você define quais operações você vai querer utilizar em uma classe.

Com isso você pode permitir que sua aplicação use objetos de classes diferentes que, pelo contrato da interface, disponibilizam pra você as mesmas operações. Contudo, cada objeto pode implementar uma operação de uma maneira diferente.

Um bom exemplo são (classes do java): java.util.List, java.util.ArrayList e java.util.LinkedList
Tanto o ArrayList como o LinkedList são usados para armazenar os itens em sequencia, mas um armazena os itens em Array e o ooutro em uma lista ligada. isso implica que várias operações - como um add e remove, por exemplo - tenham implementações distintas mas, por força de contrato, atendem pelo mesmo nome.

A interface é extremamente útil quando você tem esses casos. Mas ela tbm é útil quando você quer que um mesmo objeto possa se comportar de várias maneiras diferentes. Por exemplo:
Você possui duas interfaces: “Bola” e outra "Tampa"
Na interface “Bola” você tem definidas as ações que podem ser executadas com a bola - “quicar” ou “pular” por exemplo.
Na interface “Tampa” você tem definidas as ações que podem ser executadas com uma tampa - “tampar” - por exemplo.

Agora, imagine que você tem uma classe “TampaDeGarrafa” que implementa as duas interfaces - “Bola” e “Tampa”. E, dessa forma, um objeto da classe “TampaDeGarrafa” pode ser usado como tampa e tbm pode ser sado como bola… :wink:

Acredito que você ja usou uma tampinha de garrafa como bola alguma vez na sua vida, certo? E com certeza, você já havia usado a mesma tampa em alguma garrafa antes de começar a chutá-la…

Bem… espero tê-lo ajudado.

Nao sou experiente em arquitetura, mas vou te passar o que eu entendo de qdo usar interface…

Suponhamos que vc tenha varias telas de cadastro no seu sistema… vc quer criar uma barra de botões única no seu frame Principal, e quer que todas essas telas suas forneçam implementações dos métodos “salvarRegistro()” e “novoRegistro()”…

Pra usá-los de maneira polimórfica, vc pdoeria criar um formulario, digamos, AbstractForm e assinalar esses metodos como abstract, e entao nas classes herdeiras vc “sobrecarregar” esses métodos.

Mas isso faz com que todas essas telas OBRIGATORIAMENTE herdem de AbstractForm. E só pode haver uma herança, e vc ja queimou o recurso da herança ( que é muito mais do que herdar métodos para serem sobrescritos ).

Ao invés disso, vc cria uma interface chamada InterfaceCadastro, que contem as assintaturas desses métodos, e todas telas que IMPLEMENTAREM essa interface estarão obrigadas a fornecer implementações concretas pra esses métodos. E todas essas telas podem ser tratadas como objetos do tipo InterfaceCadastro. Com isso, suas telas ficam livres pra herdar outra coisa. Ex: JInternalFrame.

Olá Alex…

Bem, como vc disse, uma interface é uma especie de contrato. Com ela você define quais operações você vai querer utilizar em uma classe.

Com isso você pode permitir que sua aplicação use objetos de classes diferentes que, pelo contrato da interface, disponibilizam pra você as mesmas operações. Contudo, cada objeto pode implementar uma operação de uma maneira diferente.

Um bom exemplo são (classes do java): java.util.List, java.util.ArrayList e java.util.LinkedList
Tanto o ArrayList como o LinkedList são usados para armazenar os itens em sequencia, mas um armazena os itens em Array e o ooutro em uma lista ligada. isso implica que várias operações - como um add e remove, por exemplo - tenham implementações distintas mas, por força de contrato, atendem pelo mesmo nome.

A interface é extremamente útil quando você tem esses casos. Mas ela tbm é útil quando você quer que um mesmo objeto possa se comportar de várias maneiras diferentes. Por exemplo:
Você possui duas interfaces: “Bola” e outra "Tampa"
Na interface “Bola” você tem definidas as ações que podem ser executadas com a bola - “quicar” ou “pular” por exemplo.
Na interface “Tampa” você tem definidas as ações que podem ser executadas com uma tampa - “tampar” - por exemplo.

Agora, imagine que você tem uma classe “TampaDeGarrafa” que implementa as duas interfaces - “Bola” e “Tampa”. E, dessa forma, um objeto da classe “TampaDeGarrafa” pode ser usado como tampa e tbm pode ser sado como bola… :wink:

Acredito que você ja usou uma tampinha de garrafa como bola alguma vez na sua vida, certo? E com certeza, você já havia usado a mesma tampa em alguma garrafa antes de começar a chutá-la…

Bem… espero tê-lo ajudado.

Tenho a forte impressão que, em java, “interfaces” ( o otken) são utilizadas para simular ducktyping.
O pessoal da suite de testes está falando para testar as -interfaces-, no sentido de “o que o camarada pode fazer”, não?

Quando teremos mais que uma implementacao para algo.
Por exemplo a interface Connection define como os vendors devem implementa-la.

Assim passamos apenas a Interface para frente e nao uma classe em especifico.

E tambem serve pra fazer ducktyping.
http://www.guj.com.br/java.tutorial.artigo.123.1.guj

Ate mais… :thumbup:

[quote=alex.lopes]Bom dia Pessoal,

Porém minha dúvida é em relação para quando de fato eu tenho que utilizar uma interface ou não.

Olhando os Mocks para JUnit (como por exemplo o EasyMock), ele diz para fazer mock em cima de interfaces (embora exista um projeto para mock em cima de classe concreta), mas se for para fazer mock apenas em interfaces, praticamente TODAS classes concretas do meu projeto terá que estar associada a alguma interface, e ao meu ver, isso é um desperdício de recursos e produtividade.

[/quote]

O seu conceito de interface está certo. O problema de forçar que todas suas classes derivem de uma interface para poder usar mockobjects é obviamente errado (vc está programando orientado aos mockobjects em vez de À sua aplicação). Contudo …
Vc deve programar para interfaces. Houve-se muito isto, mas o que significa ? Significa que vc deve sempre - e apenas - se preocupar com as interações dos objetos com os outros e portanto nos seus mecanismos (interface) e não com o seu estado. O estado cabe ao objeto se preocupar. Então uma prática , que eu acho muito intessante, é sempre começar por declarar uma interface. Por exemplo ,digamos , Cliente.
Ai vc vai definindo que me´todos quer nessa interface à medida que precisa deles no uso da classe. No caso poderiamos colocar apenas os getters e não os setters, Isto porque os setters só interessam à implementação real da interface pois alteram o seu estado.

Ai vc cria uma classe abstrata que implementa essa interface. Vc implementa os métodos comuns e genericos e deixa os outros.
Por exemplo se a sua classe aceita listenerns vc programa o mecanismo de add/remove/fire dos listeners.

Depois vc cria uma implementação concreta partindo da classe abstrata.
Quando vc precisar passar como argumento ou retorno vc declara sempre a interface. por exemplo geraFatura (Cliente c , Compra p )

Isto dá-lhe a flexibilidade de criar objetos mock e de criar diferentes tipos de implementações. Esta estrutura é tanto mais verdade quanto mais generica for a utilização da interface. Esta estrutura é usada para Collections Framework. Um clássico.
Em certas circunstancias, sobretudo em classes de dominio, pode ser trabalhoso e deproposital manter esta estrutura. É uma questão de escolhas (trade-off)

Para fazer mocks de forma simples existe a classe Proxy que gera uma classe que emula qq interface e vc constroi o miolo de forma generica.
Uma classe semelhante na biblioteca Javassist permite fazer o mesmo como classes (vc cria uma classe que herda de uma classe pai de forma generica, num processo semelhante ao de Proxy). Vale a pena conhecer estes mecanismos de reflection para criar implementações rápidas de interfaces. Depois com tempo vc cria uma implementação completamente funcional.

Qualquer biblioteca de mocks que se preze hoje em dia (ou seja, tanto EasyMock quanto JMock) suportam mocks de classes concretas sem problema algum.

Ou seja, usar mocks nao eh impedimento algum ao seu design, e portanto, nao eh um problema :slight_smile: