Interfaces e classes abstractas

10 respostas
Bruno_Cardoso

Boas,

Já li e fiz todos os exercícios do livro “Thinking in Java - 2nd” e percebi grande parte do que li e fiz mas ouve uma questão que ainda não me ficou muito claro, talvez eu venha a perceber melhor com a prática mas já agora se alguem me poder responder, a questão é a seguinte:

  • Qual é a vantagem de declarar um interface com metodos se depois na classe que vamos implementar a interface podemos adicionar mais metodos ? Eu percebi como elas funcionam mas ainda não compreendi bem a vantagem de ter uma interface ou uma classe abstracta!

10 Respostas

georgesq

Pense no seguinte, quando vc já tem pré-definido os métodos da sua classe e apartir deles cada um pode implementar diferentes atributos e funcionalidade, daí vc pode partir para uma interface, e quanto a classe abstrata é quando vc já tem o modelo da classe todo definido e somente alguns métodos serãm diferentes, daí vc implementa uma classes abstrata por esta ter métodos abstratos.

[ ] s George Queiroz

“Morcego”:
Boas,

Já li e fiz todos os exercícios do livro “Thinking in Java - 2nd” e percebi grande parte do que li e fiz mas ouve uma questão que ainda não me ficou muito claro, talvez eu venha a perceber melhor com a prática mas já agora se alguem me poder responder, a questão é a seguinte:

  • Qual é a vantagem de declarar um interface com metodos se depois na classe que vamos implementar a interface podemos adicionar mais metodos ? Eu percebi como elas funcionam mas ainda não compreendi bem a vantagem de ter uma interface ou uma classe abstracta!
C

Para entender o porque de utilizar classes abstratas e interfaces, você deve buscar ler sobre Programação orientada a objetos (sendo em java ou não).

Quando construimos softtware orientado a objetos, moldamos objetos e relacionamentos entre eles (um objeto Cliente buscando um objeto Pedido é um relacionamento), para que haja relacionamento, um objeto precisa conhecer INTERFACE de outro objeto, uma interface de um objeto pode ser definida (a grosso modo) como uma pequena lista de métodos públicos disponíveis em uma classe. Assim podemos dizer que para a classe Cliente, pouco importa OQUE exatamente acontece na classe Pedido, Cliente precisa conhecer apenas a “interface” de Pedido, não sua implementação interna.

Quando definindo uma interface, você define como será o comportamento de um objeto, e não sua implementação.

Classes abstratas geralmente representam conceitos genéricos que não podem ser instanciados (Número, Animal etc.). A classe Animal por exemplo, pode ser abstrata, pois pode variar, de acordo com o tipo do animal. A vantagem de uma classe abstrata é que você pode programar recursos comuns a todos os animais (todos tem uma String chamada especie porexemplo) e todas as classes que herdarem de Animal, possuirão estes recursos automaticamente…

Isto está longe de ser uma explicação detalhada, mas espero que pelo menos de uma aguçada para que você consiga encontrar mais material.

Abraços!

dukejeffrie

Meu, interfaces surgiram no Java pra atender a uma necessidade na programação OO que em C++ é implementada de um jeito muito feio: herança múltipla.

A idéia é que vc tem uma classe Automóvel, abstrata ou não, não importa. Ela tem métodos de acesso aos dados típicos de um automóvel, por exemplo, quantos litros de gasolina tem no tanque, ou se ele está ligado.

Aí vc quer fazer herança pra usar polimorfismo (alguém tem um dicionário? :lol:). Isto é, vc quer fazer as classes Carro e Moto sendo extensões de Automovel e aproveitando alguns métodos e reimplementando só o necessário. Polimorfismo significa que vc quer poder declarar uma variável da classe Automóvel no seu programa e atribuir um Carro ou uma Moto de forma que ele consiga chamar os métodos certos pras variáveis certas.

Agora vamos imaginar que no seu programa vc tb tem uma classe Patrimônio, abstrata ou não, que tem métodos como valorDeVenda(). Com certeza, se vc comprou um carro, ele é patrimônio seu, e vc quer modelar isso no seu programa. E agora, como a classe carro pode ser ao mesmo tempo Automovel e Patrimonio?

Em C++, eles resolveram do ponto de vista do compilador: pode ser as duas. O compilador se vira, e vc tem meios de fazer a coisa funcionar. Mas e em Java?

Em Java vc só pode ter uma classe pai, isto é, vc só pode extender 1 classe. Mas vc pode implementar várias interfaces. Assim é que eles permitem herança múltipla. Em vez de uma classe abstrata, vc declara uma interface Automóvel e uma interface Patrimônio. Sua classe Carro, concreta, pode implementar as duas interfaces e “ser vista” como Automóvel pelo código que mexe com automóveis e como Patrimonio pelo código que lida com seu imposto de renda.

Outras explicações mais filosóficas são uma tentativa de te enrolar. Ninguém nesse meio faz nada que não seja absolutamente necessário. Só nós que tamos aprendendo ainda… : )

Aliás, pra quebrar a cabeça: o que acontece quando duas interfaces diferentes têm um método com a mesma assinatura? E se mudar só o valor de retorno? Exempllo:

Interface Face1 {
  public int getValue();
}
// ... no outro arquivo, como manda o figurino, né?
Interface Face2 {
  public String getValue();
}

Quem manda na hora de escolher qual método vale?

abração!!

C

Olá colega!

Quanto às explicações filosóficas “enroladas”, existe muita enrolação por ai sim, mas isso se deve ao fato de não haver nenhuma “verdade absoluta” quando se fala em programação (na prática: não existe nenhuma técnica 100% correta em 100% dos casos) e isto fica ainda mais evidente em programação orientada a objetos onde os conceitos são bem mais abstratos. Mas mesmo assim não dá pra generalizar…

Quanto às interfaces… uma classe que implemente ambas simplesmente não compilará…

abraços!

Leandro

Pessoal, não estou bem certo disso, mas acho que a dúvida pairava em ABSTRATA OU NÃO, e vocês explicaram e detalharam conceitos de Herança, Classe (até polimorfismo)…
E várias vezes dentre as explicações eu encontrei “abstrata ou não”, e é AÍ que eu acho que tá a dúvida…

Tentando simplificar: QUANDO usar uma classe abstrata??

Tudo bem quanto a usar uma classe “pai” e ter uma porrada de “filhos”… mas porque eu teria um “pai” que não precisa ser instanciado??
Minha dúvida é semelhante pelo seguinte fator, eu já usei várias vezes alguns métodos abstratos… mas nunca precisei de uma classe completamente abstrata… quando usar??

Valeus! :slight_smile:

D

Ok, vou tentar também…

Uma classe abstrata deve ser abstrata quando possuir pelo menos um método abstrato (não implementado); uma interface possui apenas definições de métodos (todos não implementados).

Você escreve uma classe abstrata quando você conhece e pode implementar uma parte da funcionalidade (com alguns métodos funcionais) e pretende escrever subclasses mais capazes, que implementem aqueles métodos da superclasse que são abstratos (portanto não definidos) e, eventualmente, sobrepondo outros.

A interface é um contrato. Toda classe que implementar uma interface está se comprometendo a implementar os métodos declarados na(s) interface(s) que diz implementar.

Qual a utilidade disso? Considere o seguinte:

public interface Exemplo { public int getJuros(); public String calcularSaldo(); }

Um classe que implementar a interface Exemplo compromete-se a implementar os métodos getJuros() e calcularSaldo(). Sendo assim:

class Teste extends TesteAbstrato implements Exemplo { ... }

Agora, a classe concreta Teste (que extende uma classe abstrata TesteAbstrato) diz implementar a interface Exemplo.

O que ocorre é que a classe concreta é mais capaz que sua superclasse (que é abstrata, pode implementar alguns métodos que você poderá sobrepor) e jura implementar os métodos getJuros() e calcularSaldo(). Assim, o seguinte trecho é valido:

Teste t = new Teste();
   ...

if (t instanceof Exemplo) { ... }    // Ok

Considerando tudo isso, o conceito de Herança Múltipla (implementado em C++ por exemplo) é substituído pelo conceito de implementação de interfaces.

Espero ter ajudado! :slight_smile:
Abraços[/b]

dukejeffrie

Ah, meu caro Carlos… vc já tentou?? Experimente… vc vai ficar assim: :shock:

O Leandro reparou certo: o Morcego tinha dúvidas entre usar uma interface ou uma classe abstrata… mas quando é necessário usar uma classe abstrata??

Todas as vezes que eu usei uma classe abstrata, eu estava usando um padrão chamado Strategy: quando vc permite ao sistema ter várias formas de fazer um processo através de subclasses que implementam de forma diferente um mesmo método. No exemplo do Dango tinha um método getJuros();

Pense no imenso cálculo que envolve fazer o imposto de renda. Eu poderia criar uma classe com o método abstrato calculaIR(double salario) implementando todo o resto e deixando cada subclasse fazer a própria conta. (Claro que esse não é um exemplo real).

Desse jeito, vc escolhe sua estratégia com as subclasses, mas usa polimorfismo para garantir que todos os seus objetos sabem calcular seu próprio IR. Daí o nome do padrão.[/b]

C

Se bem entendi, você está sugerindo que uma classe implementando as duas interfaces que você citou compilará:

class Teste1 implements Face1,Face2 {
    // implementacao... 
}

interface Face1 {
  public int getValue();
}

interface Face2 {
  public String getValue();
}

Concorda comigo que o código acima não compila?

Bruno_Cardoso

Fiquei sem internet durante uns dias e só agora é que pude ver os vossos replays, obrigado a todos pelas explicações. Acho que já fiquei com uma ideia mais clara da funcionabilidade das classes abstractas e das interfaces mas acho que só mesmo com a prática e experiência é que irei com mais facilidade descubrir onde usar cada uma delas.

Embora já tenha percebido, pelo que eu li, que quando quero ter uma classe base que vai derivar outras subclasses e sei que nunca vou instanciar a classe base, então aí mais vale cria-la como abstrata (A não ser que os metodos da classe base façam o mesmo nas suas subclasses)

Quanto às interfaces parece-me ser mais um modo de criar uma ligação entre várias classes de um mode mais fácil e claro de obrigar uma classe a ter os metodos da interface (obrigatoriamente).

Espero não ter dito nenhuma barbaridade :slight_smile:

Portem-se!

Elvis.The.Pelvis

Carlos H está certo. O compilador acusará erro (algo do tipo “ambiguos declaration”).

Recentemente implementei um pool de recursos (baseado no livro JSP Avançado) e foi a partir desta experiência que pude finalmente visualizar quando um classe abstrata é necessária.

Como o pool era um pool de recursos genérico (pode conter conexões com BD, I/O ou beans), uma implementação via interface se mostraria bastante inificiente. Porquê?

Uma interface é um contrato uqe a classe promete cumprir, como já explicado anteriormente. Tudo bem, ela deve implementar os métodos necessários ao usuário do pool (getResource()). Agora como ficaria o código que gerencia os recursos do pool?

Se usássemos apenas interfaces, teríamos que reimplementá-los, com uma classe abstrata resolvemos o problema.

Vamos dar uma pequena analisada no código.

public abstract class AbstractResourcePool {
  /*Recursos disponíveis.*/
  protected final Vector avaiableResources = new Vector();
  /*Recursos em uso.*/
  protected final Vector inUseResources = new Vector();
  
  /*
   *Métodos abstratos
   */
  public abstract Object createResource() throws ResourceException;
  public abstract boolean isResourceValid(Object resource)
      throws ResourceException;
  public abstract void closeResource(Object resource) throws 
      ResourceException;
  
  public Object getResource() throws ResourceException {
    //Pega o primeiro recurso disponível
    //Caso não exista, cria através de createResource()
    //Após obter o recurso, avalia se ele está disponível
    //usando isResourceValid(), caso não seja,
    //procura pelo próximo recurso disponível
  }//end getResource
  
  public void recycleResource(Object resource) {
    //Devolve o recurso ao pool
  }//end recycleResource
  
  public void shutdown() throws ResourceException {
    //Finaliza o pool, invoca closeResource() para cada recurso existente
  }//end shutdown
}//end AbstractResourcePool

Agora, se quisermos um pool de conexões, bastamos estender a classe AbstractResourcePool e implementar os métodos createResource(), isResourceValid(Object resource) e closeResource(Object resource). Para este caso específico, em createResource(), criamos uma nova conexão

public Object createResource() throws ResourceException {
  try {
    return DriverManager.getConnection(dbUrl, username, password);
  } catch(SQLException e) {
    throw new ResourceException("Unable to create resource.
" +
        "Original message: " + e.getMessage());
  }//end try
}//end createResource

em closeResource() fecharíamos a conexão

public void closeResource(Object resource) throws ResourceException {
  try {
    ((Connection)resource).close();
  } catch(SQLException e) {
    throw new ResourceException("Unable to close resource.
" +
        "Original message: " + e.getMessage());
  }//end try
}//end closeResource

e em isResourceValid()

public boolean isResourceValid(Object resource) throws ResourceException {
  try {
    if (((Connection)resource).isClosed()) {
      return false;
    }//end if
  } catch (SQLException e) {
    throw new ResourceException("Error quering for resource avaiability." +
        "
Original message: " + e.getMessage());
  }
    
  return true;
}//end isResourceValid

Espero ter sido útil.

Criado 9 de dezembro de 2002
Ultima resposta 18 de dez. de 2002
Respostas 10
Participantes 7