Então, digamos que eu tenho essa interface:
public interface IBox
{
public void setSize(int size);
public int getSize();
public int getArea();
//...and so on
}
E eu tenho uma classe que a implementa:
public class Rectangle implements IBox
{
private int size;
//Methods here
}
Se eu quisesse usar a interface IBox, não posso realmente criar uma instância dela, da maneira:
public static void main(String args[])
{
Ibox myBox=new Ibox();
}
certo? Então, eu realmente teria que fazer isso:
public static void main(String args[])
{
Rectangle myBox=new Rectangle();
}
Se isso for verdade, o único objetivo das interfaces é garantir que a classe que implementa uma interface tenha os métodos corretos, conforme descrito por uma interface? Ou existe algum outro uso de interfaces?
java
oop
language-features
interface
Click Voto a favor
fonte
fonte
Respostas:
As interfaces são uma maneira de tornar seu código mais flexível. O que você faz é o seguinte:
Posteriormente, se você decidir usar um tipo diferente de caixa (talvez exista outra biblioteca, com um tipo melhor de caixa), mude seu código para:
Depois de se acostumar, você descobrirá que é uma ótima maneira (realmente essencial) de trabalhar.
Outro motivo é, por exemplo, se você deseja criar uma lista de caixas e executar alguma operação em cada uma, mas deseja que a lista contenha diferentes tipos de caixas. Em cada caixa, você pode fazer:
(supondo que o IBox tenha um método close ()) mesmo que a classe real de myBox mude dependendo de qual caixa você está na iteração.
fonte
O que torna as interfaces úteis não é o fato de que "você pode mudar de idéia e usar uma implementação diferente posteriormente e só precisa mudar o local onde o objeto é criado". Isso não é problema.
O ponto real já está no nome: eles definem uma interface que qualquer pessoa pode implementar para usar todo o código que opera nessa interface. O melhor exemplo é o
java.util.Collections
que fornece todos os tipos de métodos úteis que operam exclusivamente em interfaces, comosort()
oureverse()
paraList
. O ponto aqui é que esse código agora pode ser usado para classificar ou reverter qualquer classe que implemente asList
interfaces - não apenasArrayList
eLinkedList
, mas também as classes que você escreve, que podem ser implementadas de uma maneira que as pessoas que escreveramjava.util.Collections
nunca imaginaram.Da mesma forma, você pode escrever um código que opere em interfaces conhecidas ou interfaces definidas, e outras pessoas podem usar seu código sem precisar solicitar que você ofereça suporte às classes.
Outro uso comum de interfaces é para retornos de chamada. Por exemplo, java.swing.table.TableCellRenderer , que permite influenciar como uma tabela Swing exibe os dados em uma determinada coluna. Você implementa essa interface, transmite uma instância para
JTable
e, em algum momento durante a renderização da tabela, seu código será chamado para executar suas tarefas.fonte
you can write code that operates on well-known interfaces, or interfaces you define
Um dos muitos usos que li é onde é difícil sem várias interfaces de herança usando Java:
Agora, imagine um caso em que:
mas,
Um design melhor seria:
Animal não possui o método chew () e, em vez disso, é colocado em uma interface como:
e a classe Reptile implementa isso e não o Birds (já que o Birds não pode mastigar):
e caso dos Birds simplesmente:
fonte
Reptile
"mastiga", então não é em si "mastigável". A convenção de (às vezes) nomear interfaces O que é digno de nota deve ser aplicado apenas onde faz todo sentido. Nomear a interfacePredator
seria mais apropriado aqui.O objetivo das interfaces é o polimorfismo , também conhecido como substituição de tipo . Por exemplo, dado o seguinte método:
Ao chamar o
scale
método, você pode fornecer qualquer valor de um tipo que implemente aIBox
interface. Em outras palavras, seRectangle
eSquare
ambos implementamIBox
, você pode fornecer umRectangle
ou umSquare
onde quer queIBox
seja esperado.fonte
As interfaces permitem que as linguagens estaticamente digitadas suportem o polimorfismo. Um purista orientado a objetos insistiria que uma linguagem deveria fornecer herança, encapsulamento, modularidade e polimorfismo, a fim de ser uma linguagem orientada a objetos com todos os recursos. Em linguagens de tipo dinâmico - ou tipo pato - (como Smalltalk), o polimorfismo é trivial; no entanto, em linguagens estaticamente tipadas (como Java ou C #), o polimorfismo está longe de ser trivial (na verdade, parece superficialmente estar em desacordo com a noção de digitação forte).
Deixe-me demonstrar:
Em uma linguagem de tipo dinâmico (ou tipo pato) (como Smalltalk), todas as variáveis são referências a objetos (nada menos e nada mais.) Portanto, no Smalltalk, eu posso fazer isso:
Esse código:
makeNoise
para o porco.O mesmo código Java se pareceria com isso (assumindo que Duck e Cow são subclasses de Animal:
Tudo bem, até introduzirmos a classe Vegetable. Os vegetais têm o mesmo comportamento do Animal, mas não todos. Por exemplo, animais e vegetais podem crescer, mas claramente os vegetais não fazem barulho e os animais não podem ser colhidos.
No Smalltalk, podemos escrever o seguinte:
Isso funciona perfeitamente no Smalltalk porque é do tipo pato (se andar como um pato e grasnar como um pato - é um pato.) Nesse caso, quando uma mensagem é enviada para um objeto, é realizada uma pesquisa no a lista de métodos do receptor e, se um método correspondente for encontrado, ele será chamado. Caso contrário, algum tipo de exceção NoSuchMethodError é lançada - mas tudo é feito em tempo de execução.
Mas em Java, uma linguagem de tipo estaticamente, que tipo podemos atribuir à nossa variável? O milho precisa herdar do vegetal, para sustentar o crescimento, mas não pode herdar do animal, porque não faz barulho. A vaca precisa herdar do Animal para apoiar o makeNoise, mas não pode herdar do Vegetable porque não deve implementar a colheita. Parece que precisamos de herança múltipla - a capacidade de herdar de mais de uma classe. Mas isso acaba sendo um recurso de linguagem bastante difícil, devido a todos os casos extremos que aparecem (o que acontece quando mais de uma superclasse paralela implementa o mesmo método ?, etc.)
Junto vem interfaces ...
Se fizermos as classes Animal e Vegetal, com cada Growable implementando, podemos declarar que nossa Vaca é Animal e nosso Milho é Vegetal. Também podemos declarar que tanto os animais quanto os vegetais são cultiváveis. Isso nos permite escrever isso para crescer tudo:
E isso nos permite fazer barulhos de animais:
A vantagem da linguagem do tipo pato é que você obtém um polimorfismo muito bom: tudo o que uma classe precisa fazer para fornecer comportamento é fornecer o método. Desde que todos se saibam bem e enviem apenas mensagens que correspondam a métodos definidos, tudo ficará bem. A desvantagem é que o tipo de erro abaixo não é detectado até o tempo de execução:
Linguagens de tipo estático fornecem "programação por contrato" muito melhor, porque elas capturam os dois tipos de erro abaixo em tempo de compilação:
-
Então .... para resumir:
A implementação de interface permite especificar quais tipos de coisas os objetos podem fazer (interação) e a herança de classe permite especificar como as coisas devem ser feitas (implementação).
As interfaces nos oferecem muitos dos benefícios do polimorfismo "verdadeiro", sem sacrificar a verificação do tipo de compilador.
fonte
Normalmente, as interfaces definem a interface que você deve usar (como o nome diz ;-)). Amostra
Agora sua função
foo
aceitaArrayList
s,LinkedList
s, ... não apenas um tipo.O mais importante em Java é que você pode implementar várias interfaces, mas só pode estender UMA classe! Amostra:
é possível mas não é!Seu código acima também poderia ser:
IBox myBox = new Rectangle();
. O importante é agora que myBox contém SOMENTE os métodos / campos da IBox e não os (possivelmente existentes) outros métodos daRectangle
.fonte
Acho que você entende tudo o que as interfaces fazem, mas ainda não está imaginando as situações em que uma interface é útil.
Se você estiver instanciando, usando e liberando um objeto em um escopo restrito (por exemplo, em uma chamada de método), uma Interface não adiciona nada. Como você observou, a classe concreta é conhecida.
Onde as interfaces são úteis é quando um objeto precisa ser criado em um local e retornado a um chamador que pode não se importar com os detalhes da implementação. Vamos mudar o seu exemplo de IBox para um Shape. Agora podemos ter implementações de Shape como Rectangle, Circle, Triangle, etc. As implementações dos métodos getArea () e getSize () serão completamente diferentes para cada classe concreta.
Agora você pode usar uma fábrica com uma variedade de métodos createShape (params) que retornarão uma Shape apropriada dependendo dos parâmetros passados. Obviamente, a fábrica saberá que tipo de Shape está sendo criado, mas o chamador não terá se preocupar se é um círculo, um quadrado ou assim por diante.
Agora, imagine que você tem uma variedade de operações que precisa executar em suas formas. Talvez você precise classificá-los por área, configurá-los para um novo tamanho e exibi-los em uma interface do usuário. As Formas são criadas pela fábrica e podem ser passadas para as classes Classificador, Sizer e Display com muita facilidade. Se você precisar adicionar uma classe hexagonal em algum momento no futuro, não precisará alterar nada além da fábrica. Sem a interface, adicionar outra forma se torna um processo muito confuso.
fonte
você poderia fazer
Dessa forma, você está usando esse objeto como Ibox e não se importa com isso
Rectangle
.fonte
Square
terá um problema .... se tentar fazê-lo sem interfaces, não poderá garantir issoSquare
eRectangle
terá os mesmos métodos ... isso pode resultar em um pesadelo quando você tiver uma base de código maior ... Lembre-se, as interfaces definem um modelo.POR QUE INTERFACE ??????
Começa com um cachorro. Em particular, um pug .
O pug tem vários comportamentos:
E você tem um Labrador, que também tem um conjunto de comportamentos.
Podemos fazer alguns pugs e laboratórios:
E podemos invocar seus comportamentos:
Digamos que eu corro um canil e preciso acompanhar todos os cães que estou abrigando. Eu preciso armazenar meus pugs e labradors em matrizes separadas :
Mas isso claramente não é o ideal. Se eu também quero guardar alguns poodles , preciso alterar minha definição de Kennel para adicionar um conjunto de poodles. Na verdade, preciso de uma matriz separada para cada tipo de cachorro.
Introspecção: pugs e labradores (e poodles) são tipos de cães e têm o mesmo conjunto de comportamentos. Ou seja, podemos dizer (para os fins deste exemplo) que todos os cães podem latir, ter um nome e podem ou não ter um rabo encaracolado. Podemos usar uma interface para definir o que todos os cães podem fazer, mas deixe que os tipos específicos de cães implementem esses comportamentos específicos. A interface diz "aqui estão as coisas que todos os cães podem fazer", mas não diz como cada comportamento é feito.
Depois, altero levemente as classes Pug e Lab para implementar os comportamentos de cães. Podemos dizer que um Pug é um cachorro e um laboratório é um cachorro.
Ainda posso instanciar Pugs e laboratórios como fiz anteriormente, mas agora também tenho uma nova maneira de fazer isso:
Isso diz que d1 não é apenas um cão, é especificamente um Pug. E d2 também é um cão, especificamente um laboratório. Podemos invocar os comportamentos e eles funcionam como antes:
Aqui é onde todo o trabalho extra compensa. A classe Kennel se torna muito mais simples. Eu preciso apenas de uma matriz e um método addDog. Ambos irão trabalhar com qualquer objeto que seja um cachorro; isto é, objetos que implementam a interface Dog.
Veja como usá-lo:
A última declaração seria exibida: Spot Fido
Uma interface permite especificar um conjunto de comportamentos que todas as classes que implementam a interface compartilharão em comum. Conseqüentemente, podemos definir variáveis e coleções (como matrizes) que não precisam saber com antecedência que tipo de objeto específico elas conterão, apenas que elas conterão objetos que implementam a interface.
fonte
Um ótimo exemplo de como as interfaces são usadas está na estrutura de coleções. Se você escreve uma função que aceita a
List
, então não importa se o usuário passa umVector
ou umArrayList
ou umHashList
ou o que quer. E você pode passar issoList
para qualquer função que exija uma interfaceCollection
ouIterable
também.Isso torna as funções
Collections.sort(List list)
possíveis, independentemente de como issoList
é implementado.fonte
Essa é a razão pela qual os Padrões de Fábrica e outros padrões criacionais são tão populares em Java. Você está certo de que, sem eles, o Java não fornece um mecanismo pronto para uso para fácil abstração da instanciação. Ainda assim, você obtém abstração em todos os lugares em que não cria um objeto no seu método, que deve ser a maior parte do seu código.
Como um aparte, geralmente incentivo as pessoas a não seguirem o mecanismo "IRealname" para nomear interfaces. Isso é algo do Windows / COM que coloca um pé no túmulo da notação húngara e realmente não é necessário (Java já é fortemente tipado, e o objetivo de ter interfaces é tê-las o mais amplamente indistinguíveis dos tipos de classe possível).
fonte
Não se esqueça de que, posteriormente, você poderá ter uma classe existente e implementá-la
IBox
, e ela ficará disponível para todo o seu código de reconhecimento de caixa.Isso fica um pouco mais claro se as interfaces forem nomeadas como -able . por exemplo
etc. (Os esquemas de nomeação nem sempre funcionam, por exemplo, não tenho certeza se
Boxable
é apropriado aqui)fonte
Estou atualizando a resposta com novos recursos da interface, que foram introduzidos no java 8 versão .
Na página de documentação da Oracle no resumo da interface :
Uma declaração de interface pode conter
Os únicos métodos que possuem implementações são métodos padrão e estáticos.
Usos da interface :
Serializable
interface podem ou não ter qualquer relação entre elas, exceto a implementação dessa interfaceAlgumas questões relacionadas ao SE relacionadas à diferença entre classe abstrata e interface e casos de uso com exemplos de trabalho:
Qual é a diferença entre uma interface e uma classe abstrata?
Como devo ter explicado a diferença entre uma interface e uma classe abstrata?
Dê uma olhada na página de documentação para entender os novos recursos adicionados no java 8: métodos padrão e métodos estáticos .
fonte
O objetivo das interfaces é abstração ou dissociação da implementação.
Se você introduzir uma abstração em seu programa, não se importará com as possíveis implementações. Você está interessado no que ele pode fazer e não em como , e você usa um
interface
para expressar isso em Java.fonte
Se você tiver CardboardBox e HtmlBox (os quais implementam o IBox), poderá passar os dois para qualquer método que aceite um IBox. Mesmo sendo ambos muito diferentes e não totalmente intercambiáveis, os métodos que não se preocupam com "abrir" ou "redimensionar" ainda podem usar suas aulas (talvez porque se preocupem com quantos pixels são necessários para exibir algo na tela).
fonte
Interfaces onde uma fetature foi adicionada ao java para permitir herança múltipla. Os desenvolvedores de Java, no entanto, perceberam que ter uma herança múltipla era um recurso "perigoso", por isso surgiu a idéia de uma interface.
herança múltipla é perigosa porque você pode ter uma classe como a seguinte:
Qual seria o método que deveria ser chamado quando usamos
Todos os problemas são resolvidos com interfaces, porque você sabe que pode estender as interfaces e que elas não terão métodos de classificação ... é claro que o compilador é bom e informa se você não implementou um método, mas eu gosto de pensar que é um efeito colateral de uma ideia mais interessante.
fonte
Aqui está o meu entendimento da vantagem da interface. Corrija-me se eu estiver errada. Imagine que estamos desenvolvendo sistema operacional e outra equipe está desenvolvendo os drivers para alguns dispositivos. Por isso, desenvolvemos uma interface StorageDevice. Temos duas implementações (FDD e HDD) fornecidas por outra equipe de desenvolvedores.
Em seguida, temos uma classe OperatingSystem que pode chamar métodos de interface como saveData, apenas passando uma instância da classe implementada na interface StorageDevice.
A vantagem aqui é que não nos importamos com a implementação da interface. A outra equipe fará o trabalho implementando a interface StorageDevice.
fonte