Vamos entender um pouco sobre a diferença entre classes abstratas e interfaces.

São comuns os questionamentos: Quando devo usar uma classe abstrata? Quando devo usar uma Interface? Devo usar as duas?

Na verdade, uma Classe Abstrata sem qualquer implementação, tem o aspect parecido com uma Interface. Mas ambas possuem várias diferenças e similaridades entre si. Pensando neste tipo de dúvida, este pequeno artigo tenta elucidar algumas questões.

Interfaces

Vamos começar com as interfaces, já tão faladas em outros artigos. Uma interface nada mais é que um conjunto de declarações de métodos o qual a implementação é obrigatória para todas as classes que implementam a interface.

Eu já li em vários lugares que a interface pode ser pensada como um contrato, e a analogia faz sentido. Um contrato apresenta clausulas que precisam ser cumpridas. Uma classe que implementa uma interface precisa ter todos os métodos que foram declarados na interface.

Por exemplo se temos a interface ITeste:

public interface ITeste
{
    void Metodo1();
    int Metodo2(int i, int j);
}

Se a classe Teste implementar a interface ITeste, não há alternativa, a classe Teste precisa ter os dois métodos declarados na interface. E como você pode perceber, os métodos da interface são públicos. E isso faz todo o sentido, já que todo o programa sabe que esta classe implementa a interface – ou seja, esta classe tem os métodos em questão.

class Teste : ITeste
{
    public void Metodo1()
    {
    }

    public int Metodo2(int i, int j)
    {
        return 0;
    }
}

Uma vantagem das interfaces é que ela permite que classes que não tem relação lógica alguma possam ser ‘agrupadas’. Por exemplo, vamos imaginar a interface ILog, que serve para escrever mensagens num log, como abaixo:

public interface ILog
{
    void EscreveLog(string mensagem);
}

Podemos então fazer as classes LogTxt e LogXml (ambas implementando ILog).
Estas classes não têm relação entre si (cada uma lida com a escrita de log de sua forma), mas a interface as ‘agrupa’.

class LogTxt : ILog
{
    public void EscreveLog(string mensagem)
    {
        // logica para log num txt
    }
}
class LogXml : ILog
{
    public void EscreveLog(string mensagem)
    {
        // logica para log num xml
    }
}

Tanto que qualquer método que precisa escrever algum log pode ter um ILog como parâmetro. Daí você pode passar qualquer classe que implemente ILog (e nem importa se o método EscreveLog realmente funcione, desde que esteja implementado).

public void MetodoExemplo(ILog log)
{
    log.EscreveLog("");
}

Classes abstratas

Classes abstratas podem ser pensadas como interfaces com mais recursos. Antes de mais nada, uma classe abstrata é uma classe – sim parece óbvio, mas lembre-se que uma classe tem métodos (e não apenas assinaturas de métodos) e variáveis.

Por exemplo, pense na classe abstrata ClasseTesteAbstract. Ela tem variáveis internas e dois métodos Protected. Note que os métodos já apresentam programação, o que não é possível numa interface.

public abstract class ClasseTesteAbstract
{
    public int i1;
    public double d3;

    public int Metodo1(int i)
    {
        return -i;
    }

    public double Metodo2(double d1, double d2)
    {
        return d1*d2;
    }
}

Classes abstratas são abstratas porque não podem ser instanciadas. Então a linha de código abaixo não pode ser feita.

var teste = new ClasseTesteAbstract(); // errado e impossível

O que precisamos fazer é usar o recurso de herança das linguagens orientadas a objetos. Vamos criar a SubclasseTeste que herda de ClasseTesteAbstract. Note que não adicionamos nenhum código na classe, porque ele já herdou todo o código da ClasseTesteAbstract.

public class SubclasseTeste : ClasseTesteAbstract
{

}

Com isso, conseguimos fazer algo assim:

var subc = new SubclasseTeste();
subc.Metodo1(18);
subc.Metodo2(5.5, 6.6);
var valor_inteiro = subc.i1;
var valor_double = subc.d3;

Ou seja, a classe abstrata pode impor a programação de métodos – e, através do recurso de sobrecarga, uma subclasse pode cancelar esta imposição ou trabalhar por cima dela (mas isto é assunto para outro artigo).

Numa primeira análise, pode parecer que classes abstratas são melhores que interfaces, mas se voltarmos ao exemplo das interfaces (com as classes LogTxt e LogXml), uma classe abstrata não ajudaria em nada neste caso, pois não faria sentido a imposição de um código sendo que cada classe tem sua própria programação.

Então o fator determinante para o uso de interfaces ou de classes abstratas é a imposição da programação dos métodos. Ora. se várias classes apresentam métodos com a mesma programação base, provavelmente vale a pena usar uma classe abstrata para diminuir a repetição de código (aliás, esta é uma das várias vantagens da orientação a objetos).

Interfaces, por outro lado, tem o objetivo de garantir que diferentes classes, que não têm nenhuma relação entre si, apresentem o mesmo conjunto básico de métodos. Uma abordagem não substitui a outra, muito pelo contrário – o que você mais encontra são classes do .NET (por exemplo) que herdam de outra classe e implementam uma ou mais interfaces.

Deixe uma resposta

Esse site utiliza o Akismet para reduzir spam. Aprenda como seus dados de comentários são processados.

Post Navigation