it-swarm-pt.tech

Por que usar interfaces, herança múltipla versus interfaces, benefícios das interfaces?

Eu ainda tenho alguma confusão sobre isso. O que eu encontrei até agora é

(Perguntas semelhantes já foram feitas aqui, mas eu estava tendo alguns outros pontos.)

  1. Interface é uma coleção de APENAS métodos abstratos e campos finais.

  2. Não há herança múltipla em Java.

  3. As interfaces podem ser usadas para obter herança múltipla em Java.

  4. Um ponto forte da herança é que podemos usar o código da classe base na classe derivada sem escrevê-lo novamente. Pode ser que essa seja a coisa mais importante para a herança estar lá.

Agora..

Q1 Como as interfaces estão tendo apenas métodos abstratos (sem código), como podemos dizer que, se estamos implementando alguma interface, ela é herança? Não estamos usando seu código.

Q2 Se a implementação de uma interface não é uma herança, então Como as interfaces são usadas para obter herança múltipla?

Q3 De qualquer forma, qual é o benefício do uso de interfaces? Eles não estão tendo nenhum código. Precisamos escrever código repetidamente em todas as classes que o implementamos.

Então por que fazer interfaces?

NOTA: Encontrei um caso em que as interfaces são úteis. Um exemplo disso é como na interface Runnable, temos o método public void run () no qual definimos a funcionalidade do encadeamento e existe uma codificação embutida de que esse método será executado como um encadeamento separado. Portanto, precisamos apenas codificar o que fazer no encadeamento, o Rest é predefinido. Mas isso também pode ser alcançado usando classes abstratas e tudo.

Então, quais são os benefícios exatos do uso de interfaces? É realmente herança múltipla que obtemos usando interfaces?

62
gprathour

Interfaces são uma coleção de campos estáticos finais e métodos abstratos (recentemente Java 8 adicionado suporte a ter métodos estáticos em uma interface).

As interfaces são feitas em situações em que sabemos que alguma tarefa deve ser executada, mas como deve ser executada pode variar. Em outras palavras, podemos dizer que implementamos interfaces para que nossa classe comece a se comportar de uma maneira específica.

Deixe-me explicar com um exemplo, todos sabemos o que são animais. Como o leão é um animal, o macaco é um animal, o elefante é um animal, a vaca é um animal e assim por diante. Agora sabemos que todos os animais comem alguma coisa e dormem. Mas a maneira como cada animal pode comer algo ou dormir pode ser diferente. Como o leão come caçando outros animais, onde a vaca come grama. Mas ambos comem. Para que possamos ter algum pseudo-código como este,

interface Animal {
    public void eat();
    public void sleep();   
}

class Lion implements Animal {
    public void eat() {
        // Lion's way to eat
    }

    public void sleep(){
         // Lion's way to sleep
    }
}

class Monkey implements Animal {
    public void eat() {
        // Monkey's way to eat
    }

    public void sleep() {
        // Monkey's way to sleep
    }
}

De acordo com o pseudo-código mencionado acima, qualquer coisa capaz de comer ou dormir será chamada de animal ou podemos dizer que é obrigatório que todos os animais comam e durmam, mas a maneira de comer e dormir depende do animal.

No caso de interfaces, herdamos apenas o comportamento, não o código real, como no caso da herança de classes.

Q1 Como as interfaces estão tendo apenas métodos abstratos (sem código), como podemos dizer que, se estamos implementando alguma interface, ela é herança? Não estamos usando seu código.

Implementar interfaces é outro tipo de herança. Não é semelhante à herança de classes, pois nessa classe filho de herança, o código real é reutilizado da classe base.

Q2 Se a implementação de uma interface não é uma herança, então Como as interfaces são usadas para obter herança múltipla?

Diz-se porque uma classe pode implementar mais de uma interface. Mas precisamos entender que essa herança é diferente da herança de classes.

Q3 De qualquer forma, qual é o benefício do uso de interfaces? Eles não estão tendo nenhum código. Precisamos escrever código repetidamente em todas as classes que o implementamos.

A implementação de uma interface impõe à classe que ela deve substituir todos os seus métodos abstratos.

Leia mais em meu livro aqui e aqui

20
gprathour

Q1 Como as interfaces estão tendo apenas métodos abstratos (sem código), como podemos dizer que, se estamos implementando alguma interface, ela é herança? Não estamos usando seu código.

Nós não podemos. As interfaces não são usadas para obter herança múltipla. Eles o substituem por uma construção mais segura, embora um pouco menos poderosa. Observe a palavra-chave implements em vez de extends.

Q2 Se a implementação de uma interface não é uma herança, então Como as interfaces são usadas para obter herança múltipla?

Eles não são. Com interfaces, uma única classe pode ter várias " visualizações ", APIs ou recursos diferentes. Por exemplo. Uma classe pode ser Runnable e Callable ao mesmo tempo, enquanto ambos os métodos estão efetivamente fazendo a mesma coisa.

Q3 De qualquer forma, qual é o benefício do uso de interfaces? Eles não estão tendo nenhum código. Precisamos escrever código repetidamente em todas as classes que o implementamos.

As interfaces são do tipo herança múltipla, sem problemas que o último apresenta (como o problema ) do diamante ).

Existem poucos casos de uso para interfaces:

  1. O objeto efetivamente tem duas identidades: a Tank é tanto um Vehicle como uma Weapon. Você pode usar uma instância de Tank em que o primeiro ou o último é esperado (polimorfismo). Isso raramente é um caso na vida real e é realmente um exemplo válido em que herança múltipla seria melhor (ou características).

  2. Responsabilidades simples: uma instância do objeto Tank em um jogo também é Runnable para permitir que você o execute em um encadeamento e um ActionListener para responder aos eventos do mouse.

  3. Interfaces de retorno de chamada: se o objeto implementar uma determinada interface de retorno de chamada, ele será notificado sobre seu ciclo de vida ou outros eventos.

  4. Interfaces de marcador: não adicionando nenhum método, mas facilmente acessível via instanceof para descobrir recursos ou desejos do objeto. Serializable e Cloneable são exemplos disso.

O que você está procurando é uma característica (como no Scala), infelizmente indisponível no Java.

36
Tomasz Nurkiewicz

BEIJO

Eu pesquisei por dias, semanas não, tentando entender interfaces e parece ler a mesma ajuda genérica; Eu não estou tentando menosprezar as contribuições, mas acho que a lâmpada apenas clicou, então estou chuff :))

Eu prefiro mantê-lo simples, estúpido, por isso apresentarei minha nova visualização encontrada de interfaces.

Eu sou um codificador casual, mas quero postar esse código que escrevi no VB.NET (o princípio é o mesmo para outras linguagens), para ajudar outras pessoas a entenderem as interfaces.

Se eu entendi errado, informe os outros nos comentários a seguir.

Explicação

Três botões em um formulário, clicando em cada um, salva uma referência de classe diferente à variável da interface (_data). Todo o ponto de referências de classe diferentes em uma variável de interface é o que eu não entendi, pois parecia redundante; então, seu poder se torna evidente com o msgbox; eu só preciso chamar o método SAME para executar a tarefa que preciso, neste case 'GetData ()', que usa o método na classe atualmente mantida pela variável de referência da interface (_data).

Portanto, no entanto, desejo obter meus dados (de um banco de dados, da web ou de um arquivo de texto), isso só é feito usando o mesmo nome do método; o código por trás dessa implementação ... não me importo.

É fácil alterar cada código de classe usando a interface sem nenhuma dependência ... este é um objetivo principal em OO e encapsulamento.

Quando usar

Classes de código e se você perceber o mesmo verbo usado para métodos, como 'GetData ()', é um bom candidato implementar uma interface nessa classe e usar esse nome de método como uma abstração/interface.

Espero sinceramente que isso ajude um colega noob com esse princípio difícil.

Public Class Form1

Private _data As IData = Nothing

Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
    _data = New DataText()
    MsgBox(_data.GetData())
End Sub

Private Sub Button2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button2.Click
    _data = New DataDB()
    MsgBox(_data.GetData())
End Sub

Private Sub Button3_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button3.Click
    _data = New DataWeb()
    MsgBox(_data.GetData())
End Sub

End Class

Public Interface IData
Function GetData() As String
End Interface

Friend Class DataText : Implements IData

Friend Function GetData() As String Implements IData.GetData
    Return "DataText"
End Function

End Class

Friend Class DataDB : Implements IData

Friend Function GetData() As String Implements IData.GetData
    Return "DataDB"
End Function

End Class

Friend Class DataWeb : Implements IData

Friend Function GetData() As String Implements IData.GetData
    Return "DataWeb"
End Function

End Class
9
Data

Q1 Como as interfaces estão tendo apenas métodos abstratos (sem código), como podemos dizer que, se estamos implementando alguma interface, ela é herança? Não estamos usando seu código.

Infelizmente, no uso coloquial, o Word inheritance ainda é usado com frequência quando uma classe implementa uma interface, embora interface implementation seria um termo preferível - IMO, o termo inheritance deve ser usado estritamente com herança de uma classe concreta ou abstrata. Em linguagens como C++ e C #, a mesma sintaxe (ou seja, Subclass : Superclass e Class : Interface) é usado para herança de classe e implementação de interface, o que pode ter contribuído para a disseminação do uso indevido do Word inheritance com interfaces. Java tem sintaxe diferente para extending uma classe em oposição a implementing uma interface, o que é uma coisa boa.

Q2 Se a implementação de uma interface não é uma herança, então Como as interfaces são usadas para obter herança múltipla?

Você pode obter o 'efeito' de herança múltipla por meio da composição - implementando várias interfaces em uma classe e fornecendo implementações para todos os métodos, propriedades e eventos necessários para todas as interfaces da classe. Uma técnica comum de fazer isso com classes concretas é fazer relacionamentos 'has-a' (composição) com classes que implementam interfaces externas, 'conectando' a implementação a cada uma das implementações internas de classe. (Idiomas como o C++ suportam várias heranças concretas diretamente, mas criam outros problemas em potencial, como o problema dos diamantes).

Q3 De qualquer forma, qual é o benefício do uso de interfaces? Eles não estão tendo nenhum código. Precisamos escrever código repetidamente em todas as classes que o implementamos.

As interfaces permitem que as classes existentes (por exemplo, estruturas) interajam com suas novas classes sem nunca as 'ter visto' antes, devido à capacidade de se comunicar por meio de uma interface conhecida. Pense em uma interface como um contrato. Ao implementar essa interface em uma classe, você é contratualmente obrigado a cumprir as obrigações exigidas, e uma vez que esse contrato seja implementado, sua classe poderá ser usada de forma intercambiável com qualquer outro código que consome a interface.

Exemplo do mundo real

Um exemplo do "mundo real" seria a legislação e convenção (interface) em torno de uma tomada elétrica em um país específico. Cada aparelho elétrico conectado ao soquete precisa atender às especificações (contrato) que as autoridades definiram para o soquete, por exemplo, o posicionamento da linha, fios neutros e terra, a posição e a cor do interruptor liga/desliga e a conformidade com a tensão elétrica, a frequência e a corrente máxima que serão fornecidas através do interface quando este for comutado em.

O benefício de desacoplar a interface (ou seja, uma tomada de parede padrão), em vez de apenas soldar os fios, é que você pode conectar (e desconectar) um ventilador, uma chaleira, um adaptador duplo ou algum novo aparelho a ser inventado no próximo ano , mesmo que esse dispositivo não existisse quando a interface foi projetada. Por quê? Porque está em conformidade com os requisitos da interface.

Por que usar interfaces?

As interfaces são ótimas para o acoplamento livre de classes e são um dos pilares do paradigma SOLID do tio Bob, especialmente o Dependency Inversion Principle e Interface Segregation Principles.

Simplificando, ao garantir que as dependências entre classes sejam acopladas apenas em interfaces (abstrações) e não em outras classes concretas, ele permite que a dependência seja substituída por qualquer outra implementação de classe que atenda aos requisitos da interface.

Nos testes, stubs e simulações de dependências podem ser usados ​​para testar a unidade de cada classe, e a interação que a classe tem com a dependência pode ser 'espionada'.

6
StuartLC

Esta é uma pergunta muito antiga e a versão Java-8 adicionou mais recursos e poder à interface.

Uma declaração de interface pode conter

  1. assinaturas de método
  2. métodos padrão
  3. métodos estáticos
  4. definições constantes.

Os únicos métodos que possuem implementações na interface são padrão e estático métodos.

Usos da interface:

  1. Para definir um contrato
  2. Vincular classes não relacionadas a possui recursos (por exemplo, classes que implementam interface serializável podem ou não ter qualquer relação entre elas, exceto a implementação dessa interface
  3. Para fornecer implementação intercambiável por exemplo Strategy_pattern
  4. Os métodos padrão permitem adicionar novas funcionalidades às interfaces de suas bibliotecas e garantir compatibilidade binária com o código escrito para os mais antigos versões dessas interfaces
  5. Organize métodos auxiliares em suas bibliotecas com métodos estáticos (você pode manter métodos estáticos específicos para uma interface na mesma interface e não em uma classe separada)

Dê uma olhada nesta pergunta SE relacionada ao exemplo de código para entender melhor os conceitos:

Como devo ter explicado a diferença entre uma interface e uma classe abstrata?

Voltando às suas perguntas:

Q1 Como as interfaces estão tendo apenas métodos abstratos (sem código), como podemos dizer que, se estamos implementando alguma interface, ela é herança? Não estamos usando seu código.

Q2 Se a implementação de uma interface não é uma herança, então Como as interfaces são usadas para obter herança múltipla?

A interface pode conter código para métodos estáticos e padrão . Esses métodos padrão fornecem compatibilidade com versões anteriores e métodos estáticos fornecem auxiliar/utilitário funções.

Você não pode ter uma herança múltipla verdadeira em Java e a interface não é o caminho para obtê-la. A interface pode conter apenas constantes. Portanto, você não pode herdar o estado, mas pode implementar o comportamento.

Você pode substituir herança por capacidade. A interface fornece vários recursos para implementar classes.

Q3 De qualquer forma, qual é o benefício do uso de interfaces? Eles não estão tendo nenhum código. Precisamos escrever código repetidamente em todas as classes que o implementamos.

Consulte a seção " usos da interface " na minha resposta.

5
Ravindra babu

Herança é quando uma classe deriva de outra classe (que pode ser abstrata) ou de uma Interface. O ponto mais forte da orientação a objetos (herança) não é a reutilização de código (existem muitas maneiras de fazê-lo), mas o polimorfismo.

Polimorfismo é quando você tem um código que usa a interface, cujo objeto de instância pode ser de qualquer classe derivada dessa interface. Por exemplo, eu posso ter esse método: public void Pet (IAnimal animal) e esse método obterá um objeto que é uma instância de Dog ou Cat que herda de IAnimal. ou posso ter esse código: IAnimal animal e, em seguida, posso chamar um método dessa interface: animal.Eat () que Dog ou Cat pode implementar de uma maneira diferente.

A principal vantagem das interfaces é que você pode herdar de algumas delas, mas se precisar herdar de apenas uma, também poderá usar uma classe abstrata. Aqui está um artigo que explica mais sobre as diferenças entre uma classe abstrata e uma interface: http://www.codeproject.com/KB/cs/abstractsvsinterfaces.aspx

3
Ben

Pergunta antiga. Estou surpreso que ninguém tenha citado as fontes canônicas: Java: uma visão geral por James Gosling, Padrões de design: elementos de software orientado a objetos reutilizáveis da turma of Four or Effective Java por Joshua Bloch (entre outras fontes).

Vou começar com uma citação:

Uma interface é simplesmente uma especificação de um conjunto de métodos aos quais um objeto responde. Não inclui nenhuma variável ou implementação de instância. As interfaces podem ser herdadas por multiplicação (diferentemente das classes) e podem ser usadas de uma maneira mais flexível do que a estrutura rígida de herança de classe usual. (Gosling, p.8)

Agora, vamos assumir suas suposições e perguntas uma a uma (ignorarei voluntariamente os recursos do Java 8).

Premissas

Interface é uma coleção de APENAS métodos abstratos e campos finais.

Você viu a palavra-chave abstract nas interfaces Java? Não. Então você não deve considerar uma interface como uma coleção de métodos abstratos. Talvez você esteja enganado pelas chamadas interfaces C++, que são classes apenas com métodos virtuais puros. O C++, por design, não possui (e não precisa ter) interfaces, porque possui herança múltipla.

Conforme explicado por Gosling, você deve considerar uma interface como "um conjunto de métodos aos quais um objeto responde". Eu gosto de ver uma interface e a documentação associada como um contrato de serviço. Ele descreve o que você pode esperar de um objeto que implementa essa interface. A documentação deve especificar as pré e pós-condições (por exemplo, os parâmetros não devem ser nulos, a saída é sempre positiva, ...) e os invariantes (um método que não modifica o estado interno do objeto). Este contrato é o coração, eu acho, da OOP.

Não há herança múltipla em Java.

De fato.

O Java omite muitos recursos confusos e mal utilizados do C++ que, em nossa experiência, trazem mais sofrimento do que benefício. Isso consiste principalmente em sobrecarga do operador (embora tenha sobrecarga de método), herança múltipla e coerções automáticas extensas. (Gosling, p.2)

Nada para adicionar.

As interfaces podem ser usadas para obter herança múltipla em Java.

Não, simlpy porque não há herança múltipla em Java. Veja acima.

Um ponto forte da herança é que podemos usar o código da classe base na classe derivada sem escrevê-lo novamente. Pode ser que essa seja a coisa mais importante para a herança estar lá.

Isso é chamado "herança de implementação". Como você escreveu, é uma maneira conveniente de reutilizar o código.

Mas tem uma contraparte importante:

as classes pai geralmente definem pelo menos parte da representação física de suas subclasses. Como a herança expõe uma subclasse a detalhes da implementação de seus pais, é comum dizer que "a herança quebra o encapsulamento" [Sny86]. A implementação de uma subclasse torna-se tão ligada à implementação de sua classe pai que qualquer alteração na implementação do pai força a subclasse a mudar. (GOF, 1,6)

(Há uma citação semelhante no item 16 de Bloch.)

Na verdade, a herança também serve a outro propósito:

A herança de classe combina herança de interface e herança de implementação. A herança de interface define uma nova interface em termos de uma ou mais interfaces existentes. A herança de implementação define uma nova implementação em termos de uma ou mais implementações existentes. (GOF, Apêndice A)

Ambos usam a palavra-chave extends em Java. Você pode ter hierarquias de classes e hierarquias de interfaces. Os primeiros compartilham a implementação, os segundos compartilham a obrigação.

Questões

Q1 Como as interfaces estão tendo apenas métodos abstratos (sem código), como podemos dizer que, se estamos implementando alguma interface, ela é herança? Não estamos usando seu código. **

A implementação de uma interface não é herança. É implementação. Assim, a palavra-chave implements.

Q2 Se a implementação de uma interface não é uma herança, então Como as interfaces são usadas para obter herança múltipla? **

Nenhuma herança múltipla em Java. Veja acima.

Q3 De qualquer forma, qual é o benefício do uso de interfaces? Eles não estão tendo nenhum código. Precisamos escrever código repetidamente em todas as classes que o implementamos./Então, por que fazer interfaces?/Quais são os benefícios exatos do uso de interfaces? É realmente a herança múltipla que alcançamos usando interfaces?

A pergunta mais importante é: por que você gostaria de ter herança múltipla? Posso pensar em duas respostas: 1. dar tipos múltiplos a um objeto; 2. reutilizar código.

Atribuir tipos múltiplos a um objeto

No POO, um objeto pode ter tipos diferentes. Por exemplo, em Java, um ArrayList<E> Possui os seguintes tipos: Serializable, Cloneable, Iterable<E>, Collection<E>, List<E>, RandomAccess, AbstractList<E>, AbstractCollection<E> e Object (espero não ter esquecido ninguém). Se um objeto tiver tipos diferentes, vários consumidores poderão usá-lo sem conhecer suas especificidades. Eu preciso de um Iterable<E> E você me dá um ArrayList<E>? Está certo. Mas se eu precisar agora de um List<E> E você me der um ArrayList<E>, Tudo bem também. Etc.

Como você digita um objeto no OOP? Você tomou a interface Runnable como exemplo, e este exemplo é perfeito para ilustrar a resposta a esta pergunta. Cito o documento oficial Java:

Além disso, o Runnable fornece os meios para uma classe estar ativa enquanto não está subclassificando o Thread.

Aqui está o ponto: A herança é uma maneira conveniente de digitar objetos. Você deseja criar um thread? Vamos subclassificar a classe Thread. Você quer que um objeto tenha tipos diferentes, vamos usar herança múltipla. Argh. Não existe em Java. (Em C++, se você deseja que um objeto tenha tipos diferentes, herança múltipla é o caminho a seguir.)

Como dar tipos múltiplos a um objeto então? Em Java, você pode digitar seu objeto diretamente. É o que você faz quando sua classe implements a interface Runnable. Por que usar Runnable se você é um fã de herança? Talvez porque sua classe já seja uma subclasse de outra classe, digamos A. Agora sua classe tem dois tipos: A e Runnable.

Com várias interfaces, você pode atribuir vários tipos a um objeto. Você apenas precisa criar uma classe que implements múltiplas interfaces. Contanto que você esteja em conformidade com os contratos, tudo bem.

Reutilizar código

Este é um assunto difícil; Eu já citei o GOF por quebrar o encapsulamento. Outra resposta mencionou o problema do diamante. Você também pode pensar no Princípio da Responsabilidade Única:

Uma classe deve ter apenas um motivo para mudar. (Robert C. Martin, Desenvolvimento Ágil de Software, Princípios, Padrões e Práticas)

Ter uma classe pai pode dar à classe uma razão para mudar, além de suas próprias responsabilidades:

A implementação da superclasse pode mudar de release para release e, se o fizer, a subclasse pode quebrar, mesmo que seu código não tenha sido tocado. Como conseqüência, uma subclasse deve evoluir em conjunto com sua superclasse (Bloch, item 16).

Eu acrescentaria uma questão mais prosaica: sempre tenho uma sensação estranha quando tento encontrar o código fonte de um método em uma classe e não consigo encontrá-lo. Então me lembro: ele deve ser definido em algum lugar da classe pai. Ou na classe dos avós. Ou talvez até mais. Um bom IDE é um ativo valioso nesse caso, mas permanece, em minha opinião, algo mágico. Nada parecido com as hierarquias de interfaces, pois o javadoc é a única coisa de que preciso: um atalho de teclado no IDE e eu o entendi.

A herança, no entanto, tem vantagens:

É seguro usar herança dentro de um pacote, onde as implementações da subclasse e da superclasse estão sob o controle dos mesmos programadores. Também é seguro usar a herança ao estender classes especificamente projetadas e documentadas para extensão (Item 17: Design e documento da herança ou então a proíbe). (Bloch, item 16)

Um exemplo de uma classe "especificamente projetada e documentada para extensão" em Java é AbstractList.

Mas Bloch e o GOF insistem nisso: "Favorecer a composição sobre a herança":

A delegação é uma maneira de tornar a composição tão poderosa para reutilização quanto a herança [Lie86, JZ91]. Na delegação, dois objetos estão envolvidos no tratamento de uma solicitação: um objeto de recebimento delega operações ao seu delegado. Isso é análogo a subclasses que adiam solicitações para classes-pai. (GOF p.32)

Se você usar composição, não precisará escrever o mesmo código repetidamente. Você acabou de criar uma classe que lida com as duplicações e passa uma instância dessa classe para as classes que implementam o método interface. É uma maneira muito simples de reutilizar código. E isso ajuda você a seguir o Princípio da responsabilidade única e tornar o código mais testável. Rust e Go não têm herança (eles também não têm classes), mas não acho que o código seja mais redundante do que em outros idiomas OOP.

Além disso, se você usar composição, naturalmente se usará interfaces para fornecer ao código a estrutura e a flexibilidade necessárias (consulte outras respostas sobre casos de uso de interfaces).

Nota: você pode compartilhar código com Java 8 interfaces

E, finalmente, uma última citação:

Durante a memorável sessão de perguntas e respostas, alguém perguntou a ele [James Gosling]: "Se você pudesse fazer Java novamente, o que mudaria?" "Eu deixaria de fora as aulas" (em qualquer lugar da rede, não sei se isso é verdade)

2
jferard

Ambos os métodos funcionam (interfaces e herança múltipla).

Resposta rápida prática rápida

As interfaces são melhores quando você tem vários anos de experiência usando a Herança Múltipla que tem Super Classes com apenas definição de método e nenhum código.

Uma pergunta complementar pode ser: "Como e por que migrar código de Classes Abstratas para Interfaces".

Se você não estiver usando muitas classes abstratas, em seu aplicativo, ou não tiver muita experiência com ele, talvez prefira pular interfaces.

Não se apresse para usar interfaces.

Resposta Aborrecida Longa

As interfaces são muito semelhantes, ou mesmo equivalentes às Classes abstratas.

Se o seu código possui muitas classes abstratas, é hora de começar a pensar em termos de interfaces.

O código a seguir com classes abstratas:


MyStreamsClasses.Java

/* File name : MyStreamsClasses.Java */
import Java.lang.*;
// Any number of import statements

public abstract class InputStream {
  public void ReadObject(Object MyObject);
}

public abstract class OutputStream {
  public void WriteObject(Object MyObject);
}

public abstract class InputOutputStream 
    imnplements InputStream, OutputStream {
  public void DoSomethingElse();
}

Pode ser substituído por:


MyStreamsInterfaces.Java

/* File name : MyStreamsInterfaces.Java */
import Java.lang.*;
// Any number of import statements

public interface InputStream {
  public void ReadObject(Object MyObject);
}

public interface OutputStream {
  public void WriteObject(Object MyObject);
}

public interface InputOutputStream 
    extends InputStream, OutputStream {
  public void DoSomethingElse();
}

Felicidades.

2
umlcat

As interfaces são feitas para que uma classe implemente a funcionalidade na interface e se comporte de acordo com essa interface.

0
Dark Drake

Q1. Como as interfaces estão tendo apenas métodos abstratos (sem código), como podemos dizer que, se estamos implementando uma interface, ela é uma herança? Não estamos usando seu código.

Não é herança igual. É apenas semelhante. Deixe-me explicar:

VolvoV3 extends VolvoV2, and VolvoV2 extends    Volvo (Class)
VolvoV3 extends VolvoV2, and VolvoV2 implements Volvo (Interface)

line1: Volvo v = new VolvoV2(); 
line2: Volvo v = new VolvoV3(); 

Se você vir apenas as linhas 1 e 2, poderá deduzir que VolvoV2 e VolvoV3 têm o mesmo tipo. Você não pode deduzir se a Volvo é uma superclasse ou a Volvo é uma interface.

Q2. Se a implementação de uma interface não é uma herança, então Como as interfaces são usadas para obter várias heranças?

Agora usando interfaces:

VolvoXC90 implements XCModel and Volvo (Interface)
VolvoXC95 implements XCModel and Volvo (Interface)

line1: Volvo   a = new VolvoXC90();
line2: Volvo   a = new VolvoXC95();
line3: XCModel a = new VolvoXC95();

Se você vir apenas as linhas 1 e 2, poderá inferir que VolvoXC90 e VolvoXC95 têm o mesmo tipo (Volvo). Você não pode deduzir que a Volvo é uma superclasse ou a Volvo é uma interface.

Se você vir apenas as linhas 2 e 3, poderá inferir que o Volvo95 implementa dois tipos, XCModel e Volvo, em Java você sabe que pelo menos um precisa ser uma interface. Se esse código foi escrito em C++ , por exemplo, elas podem ser as duas classes, portanto, várias heranças.

Q3. De qualquer forma, qual é o benefício de usar interfaces? Eles não estão tendo nenhum código. Precisamos escrever código repetidamente em todas as classes em que o implementamos.

Imagine um sistema em que você use uma classe VolvoXC90 em 200 outras classes.

VolvoXC90 v = new VolvoXC90();

Se você precisar desenvolver seu sistema para iniciar o VolvoXC95, precisará alterar outras 200 classes.

Agora, imagine um sistema em que você use uma interface Volvo em 10.000.000 de classes.

// Create VolvoXC90 but now we need to create VolvoXC95
Volvo v = new VolvoFactory().newCurrentVolvoModel(); 

Agora, se você precisar desenvolver seu sistema para criar modelos VolvoXC95, precisará alterar apenas uma classe, a Fábrica.

É uma pergunta de senso comum. Se o seu sistema for composto apenas de poucas classes e tiver poucas atualizações, use Interfaces em qualquer lugar que seja contraproducente. Para sistemas grandes, ele pode poupar muita dor e evitar o risco de adotar interfaces.

Eu recomendo que você leia mais sobre os princípios S.O.L.I.D e leia o livro Java Efetivo. Ele tem boas lições de engenheiros de software experientes.

0
Anderson Marques

Assim. Há muitas respostas excelentes aqui explicando em detalhes o que é uma interface. No entanto, este é um exemplo de seu uso, da maneira que um dos meus melhores colegas me explicou anos atrás, com o que aprendi na universidade nos últimos dois anos.

Uma interface é uma espécie de 'contrato'. Expõe alguns métodos, campos e outros que estão disponíveis. Ele não revela nenhum dos detalhes de sua implementação, apenas o que retorna e quais parâmetros são necessários. E aqui reside a resposta para a pergunta três, e o que eu sinto é uma das maiores forças da OOP moderna:

"Código por adição, não por modificação" - Magnus Madsen, AAU

Isso é o que ele chamou pelo menos, e ele pode tê-lo de outro lugar. O código de exemplo abaixo está escrito em C #, mas tudo o que é mostrado pode ser feito da mesma maneira em Java.

O que vemos é uma classe chamada SampleApp, que possui um único campo, o IOContext. IOContext é uma interface. O SampleApp não se importa nem um pouco com a maneira como salva seus dados, apenas precisa fazê-lo, no método "doSomething ()".

Podemos imaginar que, no início do processo de desenvolvimento, salvar os dados pode ter sido mais importante do que COMO foram salvos e, portanto, o desenvolvedor optou por simplesmente escrever a classe FileContext. Mais tarde, no entanto, ele precisou dar suporte ao JSON por qualquer motivo. Então, ele escreveu a classe JSONFileContext, que herda o FileContext. Isso significa que ele é efetivamente um IOContext, que tem a funcionalidade do FileContext, salva a substituição de FileContexts SaveData e LoadData, ainda usa seus métodos de 'gravação/leitura'.

A implementação da classe JSON tem sido uma pequena quantidade de trabalho, em comparação com a escrita da classe e a herança apenas do IOContext.

O campo de SampleApp poderia ter sido apenas do tipo 'FileContext', mas, dessa forma, seria restrito a usar apenas filhos dessa classe. Ao fazer a interface, podemos até executar a implementação SQLiteContext e gravar em um banco de dados, o SampleApp nunca saberá ou se importará e, quando escrevermos a classe sql lite, precisaremos fazer apenas uma alteração em nosso código: new JSONFileContext(); se torna new SQLiteContext();

Ainda temos nossas implementações antigas e podemos voltar para elas, se necessário. Não quebramos nada e todas as alterações em nosso código são meia linha, que podem ser alteradas em um piscar de olhos.

então: Código por adição, NÃO por modificação.

namespace Sample
{
    class SampleApp
    {
        private IOContext context;

        public SampleApp()
        {
            this.context = new JSONFileContext(); //or any of the other implementations
        }

        public void doSomething()
        {
            //This app can now use the context, completely agnostic of the actual implementation details.
            object data = context.LoadData();
            //manipulate data
            context.SaveData(data);
        }
    }

    interface IOContext
    {
        void SaveData(object data);
        object LoadData();
    }

    class FileContext : IOContext
    {
        public object LoadData()
        {

            object data = null;
            var fileContents = loadFileContents();
            //Logic to turn fileContents into a data object
            return data;
        }

        public void SaveData(object data)
        {
            //logic to create filecontents from 'data'
            writeFileContents(string.Empty);
        }

        protected void writeFileContents(string fileContents)
        {
            //writes the fileContents to disk
        }

        protected string loadFileContents()
        {
            string fileContents = string.Empty;
            //loads the fileContents and returns it as a string
            return fileContents;
        }
    }

    class JSONFileContext : FileContext
    {
        public new void SaveData(object data)
        {
            //logic to create filecontents from 'data'
            base.writeFileContents(string.Empty);
        }

        public new object LoadData()
        {
            object data = null;
            var fileContents = loadFileContents();
            //Logic to turn fileContents into a data object
            return data;
        }
    }

    class SQLiteContext : IOContext
    {
        public object LoadData()
        {
            object data = null;
            //logic to read data into the data object
            return data;
        }

        public void SaveData(object data)
        {
            //logic to save the data object in the database
        }
    }
}
0
user3801839