Por que devo declarar uma classe como uma classe abstrata?

39

Eu conheço a sintaxe, regras aplicadas à classe abstrata e quero saber o uso de uma classe abstrata

Abstract class can not be instantiated directly but can be extended by other class

Qual é a vantagem de fazer isso?

Como é diferente de uma interface?

Eu sei que uma classe pode implementar várias interfaces, mas só pode estender uma classe abstrata. Essa é a única diferença entre uma interface e uma classe abstrata?

Estou ciente do uso de uma interface. Eu aprendi isso com o modelo de delegação de eventos do AWT em Java.

Em quais situações devo declarar classe como uma classe abstrata? Quais são os benefícios disso?

    
por Vaibhav Jani 29.07.2011 / 10:59
fonte

9 respostas

48

Esta resposta explica bem as diferenças entre uma classe abstrata e uma interface, mas ela não responde por que você deve declarar uma.

Do ponto de vista puramente técnico, nunca há um requisito para declarar uma classe como abstrata.

Considere as três classes a seguir:

class Database { 
    public String[] getTableNames() { return null; } //or throw an exception? who knows...
}

class SqlDatabase extends Database { } //TODO: override getTableNames

class OracleDatabase extends Database { }  //TODO: override getTableNames

Você não tem para tornar a classe Database abstrata, mesmo que exista um problema óbvio com a sua implementação: Quando você está escrevendo este programa, você pode digitar new Database() e ele será válido, mas nunca funcionaria.

Independentemente disso, você ainda obteria polimorfismo, portanto, contanto que seu programa crie apenas SqlDatabase e OracleDatabase instâncias, você poderia escrever métodos como:

public void printTableNames(Database database) {
    String[] names = database.getTableNames();
}

As classes abstratas melhoram a situação evitando que um desenvolvedor instancie a classe base, porque um desenvolvedor a marcou como tendo funcionalidade ausente . Ele também fornece segurança em tempo de compilação para que você possa garantir que quaisquer classes que estendam sua classe abstrata forneçam a funcionalidade mínima para funcionar, e você não precisa se preocupar em colocar métodos stub (como o um acima) que os herdeiros de alguma forma têm que magicamente saber que eles têm para substituir um método para que ele funcione.

Interfaces são um tópico totalmente separado. Uma interface permite descrever quais operações podem ser executadas em um objeto. Você normalmente usaria interfaces ao escrever métodos, componentes, etc., que usam os serviços de outros componentes, objetos, mas você não se importa com o tipo real de objeto do qual você está obtendo os serviços.

Considere o seguinte método:

public void saveToDatabase(IProductDatabase database) {
     database.addProduct(this.getName(), this.getPrice());
}

Você não se importa se o objeto database herda de qualquer objeto em particular, apenas se importa que ele tenha um método addProduct . Portanto, nesse caso, uma interface é mais adequada do que fazer todas as suas classes herdarem da mesma classe base.

Às vezes, a combinação dos dois funciona muito bem. Por exemplo:

abstract class RemoteDatabase implements IProductDatabase { 
    public abstract String[] connect();
    public abstract void writeRow(string col1, string col2);

    public void addProduct(String name, Double price) {
        connect();
        writeRow(name, price.toString());
    }
}

class SqlDatabase extends RemoteDatabase {
    //TODO override connect and writeRow
}

class OracleDatabase extends RemoteDatabase { 
    //TODO override connect and writeRow
}

class FileDatabase implements IProductDatabase {
    public void addProduct(String name, Double price) {
         //TODO: just write to file
    }
}

Observe como alguns dos bancos de dados herdam do RemoteDatabase para compartilhar algumas funcionalidades (como se conectar antes de gravar uma linha), mas FileDatabase é uma classe separada que implementa apenas IProductDatabase .

    
por 13.06.2012 / 22:12
fonte
15

Semelhanças

Classes e interfaces abstratas são necessárias para a abstração. Eles não podem ser instanciados com um novo , mas podem ser resolvidos em inversão de contêineres de controle ou por padrões de fábrica.

Diferença

  1. Interfaces

    • Definir contrato público bem conhecido, habilidades do tipo
    • Aplicável para mostrar herança horizontal, ou seja, ramificação no primeiro nível de herança (por exemplo, ILog para definir recursos de registro em banco de dados, arquivo de texto, XML, SOAP, etc.)
    • Todos os membros são públicos
    • Nenhuma implementação permitida
    • O filho de herança pode ter muitas interfaces para implementar
    • Útil para integração de terceiros
    • A nomeação geralmente começa com I
  2. Classe abstrata

    • Defina estrutura, identidade e algum comportamento suportado padrão
    • Aplicável para mostrar herança vertical, ou seja, ramificação profunda nos vários níveis (por exemplo, classe AbstractEntity no desenvolvimento orientado por domínio)
    • Os membros podem ter visibilidade diferente (de público para privado)
    • Você pode implementar alguns membros (por exemplo, * classes do Reader)
    • Filho de herança pode ter apenas uma classe abstrata de base

Na verdade, é fácil encontrar a resposta em simples consulta ao google .

    
por 29.07.2011 / 11:31
fonte
11

How it is different from an Interface?

Em uma classe abstrata, você pode implementar alguns métodos e deixar (forçar) o restante a ser implementado pela classe de extensão. Você não pode implementar métodos em uma interface. Você não pode forçar ninguém a anular qualquer coisa ao estender uma aula ordinária. Com uma aula abstrata, você pode.

    
por 29.07.2011 / 11:08
fonte
8

Classes abstratas são para "é um" relacionamento e interfaces são para "pode fazer".

As classes abstratas permitem que você adicione o comportamento base para que os programadores não tenham que codificar tudo, enquanto ainda os forçam a seguir seu design.

    
por 16.08.2012 / 15:00
fonte
3

Além dos detalhes técnicos profundos - como a implementação de alguns métodos para classes abstratas, etc., o significado é assim:

As interfaces definem a capacidade comum - IEnumerable define que a classe que implementa essa interface pode ser enumerada. Não diz nada sobre a própria aula.

As classes abstratas (ou básicas) definem o comportamento - o WebRequest define um comportamento comum de todas as classes filhas, como HttpWebRequest, etc. Ele define o significado central da classe e sua finalidade real - acessar recursos da Web.

    
por 29.07.2011 / 18:23
fonte
2

entrada da Wikipedia .

As principais diferenças entre uma interface e uma classe abstrata é que uma classe abstrata pode fornecer métodos implementados. Com as interfaces você só pode declarar os métodos, escrever sua assinatura. Aqui está um exemplo de uma classe que estende uma classe abstrata que implementa duas interfaces: (java)

interface MyInterface1 {
  string getValue1();
}

interface MyInterface2 {
  string getValue2();
}

abstract class MyAbstractClass implements MyInterface1, MyInterface2{
  void printValues() {
    System.out.println("Value 1: " + getValue1() + ", Value 2: " + getValue2() + 
                       ", Value 3: " + getValue3());
  }

  protected abstract string getValue3();
}

class ImpClass extends MyAbstractClass {
  public string getValue1() {
    return "1";
  }

  public string getValue2() {
    return "2";
  }

  protected string getValue3() {
    return "3";
  }
}

Neste exemplo, o MyAbstractClass fornece um método público que imprime todos os três valores. Em ImpClass você precisa implementar getValue1 e getValue2 respectivamente de MyInterface1 e MyInterface2 e getValue3 da classe abstrata.

Voilà.

Existem mais aspectos (interface: somente métodos públicos, classe abstrata: métodos de resumo protegido e resumo público), mas você pode ler isso por si mesmo.

Em uma nota final, uma classe abstrata que fornece apenas métodos abstratos é uma classe base abstrata "pura", também conhecida como interface.

    
por 29.07.2011 / 11:17
fonte
2
  • Interface - quando algumas classes compartilham uma API (nomes e parâmetros de métodos)
  • Classe abstrata - quando algumas classes compartilham o mesmo código (implementação)

Em outras palavras, você deve começar com uma pergunta: "essas classes necessariamente compartilham a implementação , ou elas possuem apenas uma interface ?"

Se a resposta for mista, como - essas três classes devem compartilhar a implementação, mas essas outras duas compartilham apenas sua API - então você pode criar uma interface para todas as cinco e uma classe abstrata para essas três. com o código comum.

Há também outras maneiras de compartilhar a implementação, por exemplo, para encapsular um objeto com essa implementação (por exemplo, no padrão Strategy ).

    
por 17.08.2012 / 10:35
fonte
1

Você declararia um resumo de classe quando não quiser que o desenvolvedor (provavelmente você mesmo) possa instanciá-lo, porque não funcionaria ou não faria sentido.

Por exemplo, considere um jogo em que existem diferentes tipos de entidades de jogo. Todos eles herdam da base GameEntity class.

abstract class GameEntity{

    int lifePoint, speed, damage;

    public attack(GameEntity target){ target.damage(damage); }

    public damage(int damageInflicted){ lifePoint -= damageInflicted - speed; }

    // etc...

}

Esta classe é declarada abstract , pois não faria sentido instanciá-la. Ele declara algumas ações para as entidades do jogo e alguns atributos, mas em nenhum lugar nessa classe esses atributos são inicializados. Essa classe serve como um modelo para as entidades do jogo, mas não deve ser instanciada por conta própria e, como tal, declarada abstract .

Com relação à diferença de uso entre uma classe abstrata e uma interface:

Do meu ponto de vista, uma interface é uma maneira de obter um comportamento polimórfico sem ser limitada pelo mecanismo de herança única de algumas linguagens.

Vamos voltar ao jogo como um exemplo. Considere uma classe Enemy que é derivada de GameEntity . Esta classe tem um método attackMeFromDistance(RangedAttacker attacker) . Este método destina-se a permitir que entidades ataquem o inimigo de longe.

Como você pode ver, esse método usa um tipo RangedAttacker como parâmetro. No entanto, todas as entidades do jogo já herdam de GameEntity . Eles não podem estender outra classe.

Pegue as classes Mage e Archer por exemplo. Queremos permitir que ambos sejam aceitos como parâmetros no método attackMeFromDistance(RangedAttacker attacker) , mas eles já são derivados de GameEntity .

Para resolver isso, criamos uma nova interface:

interface RangedAttacker{
    public void attackFromDistance();
}

Uma classe que implementa essa interface deve implementar o método attackFromDistance() e, portanto, é garantido que ele tenha recursos de ataque à distância. Isso significa que o método attackMeFromDistance agora pode aceitar com segurança as classes que implementam essa interface. Então, fazer Mage e Archer implementar essa interface resolve nosso problema.

Para mim, esse é o poder das interfaces.

Então, para resumir, você usaria normalmente uma classe abstrata quando quiser ter uma classe base para algumas classes, mas não faria sentido instanciá-la sozinha (ou em um caso em que ela tenha abstract métodos, que devem ser implementados pelas subclasses e, nesse caso, o compilador o obrigaria a criar a classe abstract ). Você usaria uma interface para obter um comportamento polimórfico sem ser limitado pelo mecanismo de herança única.

    
por 14.04.2014 / 12:40
fonte
0
  1. Há chance de que poucos métodos sejam comuns a alguma classe (lógica de negócios). E os métodos restantes são diferentes. Nesse tipo de cenário, você pode implementar todos os métodos comuns em uma classe e declarar o restante como abstrato. Então você deve declarar a classe como abstrata.
  2. Às vezes, você não permite criar o objeto para a turma diretamente. Esse tipo de classe você precisa declarar a classe como abstrata.
por 12.10.2012 / 20:34
fonte