Polimorfismo: Classes abstratas e Métodos abstratos


Classes e Métodos abstratos em JavaDesde que iniciamos nossos tutoriais sobre classes e objetos vínhamos tratando as classes como entidades 'reais' ou 'concretas', pois podíamos instanciar objetos a partir dela.

Nesse artigo vamos introduzir um conceito importante e bastante útil na orientação a objetos: a abstração.

Pode parecer estranho, ou no mínimo confuso, classificar e utilizar algo que se diz ser abstrato, mas veremos que esse tipo de idéia é bem interessante e bem mais realista que nossa noção antiga de classe e objeto.

O que são classes abstratas em Java

Ao pé da letra, a definição de classe abstrata é: classes que não serão instanciadas.
Ou seja, são classes em que não criaremos nenhum objeto dela, diretamente.
Para evitar confusão, é mais correto se referir a esse tipo de classes como superclasses abstratas.

Então, qual o sentido de se ter classes em que nunca vamos instanciar um objeto a partir delas?
Se você for perspicaz, deve ter notado as palavras 'diretamente' e 'superclasse'.
Não vamos criar objetos dessas superclasses abstratas, mas sim de suas subclasses.
Por isso que explicamos em detalhes os conceitos de herança antes de introduzir os de polimorfismo.


Classes abstratas no mundo real

Usamos classes abstratas para representar grupos que tem características comum, mas que, em alguns detalhes específicos, agem de maneira diferente.
Note que as classes abstratas são bastante relacionadas com polimorfismo em Java.

Vamos aos nossos exemplos práticos.
Se você for a uma concessionária para comprar um veículo, você nunca irá escolher um "Carro", você escolhe um gol, um fiat, enfim, um modelo específico.

Se for dono de um empresa e for contratar alguém, você não contra simplesmente um "Funcionario", você contrata uma secretárias, um técnico de TI, enfim, você contrata alguém com uma profissão específica para fazer ma função específica.

Do tutorial passado sobre os animais no joguinho da Colheita Feliz, você não vai colocar um "Animal" no jogo, você coloca uma vaca, um cão ou uma ovelha. Ou seja, um animal específico.

Na verdade, em nosso mundo real, só existem objetos. As classes são abstratas, servem para classificar grupos de objetos.
Por exemplo, "Carro" é uma classe abstrata que reúne um conjunto de características que classificam os carros: potência do motor, possuem pneus, possuem portas, se locomovem etc.
"Funcionario" é uma classe abstrata que reúne um conjunto de características, gerais, de um funcionário: tem salário, uma missão na empresa, pagam impostos, tem um chefe etc.

Ou seja, não existe "Carro", existe fusca ou ferrari.
Ninguém pede carne de "Animal" na churrascaria, e sim de boi ou carneiro.
E ninguém se candidata a uma vaga para trabalhar como "Funcionario".

São apenas modelos, abstrações que agrupam e definem um conjunto de objetos com características semelhantes.
Classes abstratas são superclasses que servem como modelo. Esses modelos possuem, no entanto, somente as características gerais.

Por que gerais?
Ora, não podemos dizer qual a potência do motor do "Carro", nem o número de portas ou quantos quilômetros fazem com 1 litro. Isso é uma característica de cada tipo específico de carro.
Também não podemos dizer que "Animal" berra ou late, ou se é herbívoro ou carnívoro.
Muito menos podemos especificar o salário de um "Funcionário" ou que as línguas estrangeiras que sabem ou função desempenhada, pois isso são características específicas.

Vale lembrar que podemos também ter subclasses abstratas.
Por exemplo, "Animal" é abstrato, e as subclasses "Mamiferos" e "Repteis" também seriam abstratas, pois são um modelo para um grupo mais específico e seleto de animais.
E da classe "Carro", que subclasses, também abstratas porém mais específicas, poderíamos citar?
"Volkswagen", "Toyota" etc.

Logo, classes abstratas servem para criar um modelo, um conjunto de características bem gerais.


Para que servem as classes abstratas e os métodos abstratos em Java

Tínhamos citado, em nosso tutorial de Java passado, que através do polimorfismo as subclasses poderiam se portar de maneira diferente.

Abstração e polimorfismo estão intimamente relacionados.
Vamos criar classes abstratas, e declarar somente o cabeçalho dos métodos. Esses serão os métodos abstratos: somente vamos dizer que tipos de métodos existem, através da declaração deles.

Não podemos definir e criar o código desses métodos por uma razão bem óbvia: os métodos vão se comportar de modo diferente nas subclasses, ora. Porém, eles terão o mesmo nome.

Declarando classes abstratas e métodos abstratos em Java
Usamos, em ambos casos, a keyword 'abstract' logo após o modificador de acesso (ou seja, logo após public, private ou protected):

classes: public abstract class Animal { ... }
método: public abstract void som() { ... }

Quando for implementar os métodos nas subclasses, não esqueça de usar o @Override.

Exemplo de código em Java: Polimorfismo e abstração dos animais

Note que podemos declarar variáveis, criar construtores e métodos que serão o mesmo em todas as subclasses.
Porém, os métodos que serão diferentes em cada subclasse nós apenas declaramos seu cabeçalho.

Vamos usar as variáveis "nome" e "numeroPatas" na superclasse abstrata, porém o método som(), que cada objeto emite, será diferente.
Depois, criamos um objeto para cada tipo diferente de objeto e invocamos o método som() de cada um, e você verá que, embora todos façam parte da superclasse abstrata "Animal", eles vão agir de forma diferente.
É a união da herança, polimorfismo e abstração:


-->Bichos.java
public class Bichos {

    public static void main(String[] args) {
        Vaca mimosa = new Vaca();
        Gato bichano = new Gato();
        Carneiro barnabe = new Carneiro();
        
        mimosa.som();
        bichano.som();
        barnabe.som();

    }

}



-->Animal.java
public abstract class Animal {
    protected String nome;
    protected int numeroPatas;
    
    public abstract void som();

}



-->Vaca.java
public class Vaca extends Animal {
    public Vaca(){
        this.nome = "Vaca";
        this.numeroPatas = 4;
        
    }
    @Override    
    public void som(){
        System.out.println("A " + this.nome + " que tem " + this.numeroPatas + " patas, faz MUUUU");
    }

}



-->Gato.java
public class Gato extends Animal{
    public Gato(){
        this.nome = "Gato";
        this.numeroPatas = 4;
        
    }
    @Override    
    public void som(){
        System.out.println("O " + this.nome + " que tem " + this.numeroPatas + " patas, faz MIAU");
    }
}



-->Carneiro.java
public class Carneiro extends Animal{
    public Carneiro(){
        this.nome = "Carneiro";
        this.numeroPatas = 4;
        
    }
    
    @Override
    public void som(){
        System.out.println("O " + this.nome + " que tem " + this.numeroPatas + " patas, faz BÉÉÉ");
} }

10 comentários:

Anônimo disse...

Quem ainda tiver em dúvida leia e repita isso por 5 vezes aqui esta a resposta desse assunto

Na verdade, em nosso mundo real, só existem objetos. As classes são abstratas, servem para classificar grupos de objetos.


perfeito !!!!

Anônimo disse...

Muito bom mais... no caso tenho que fazer o planejamento antes supondo que qndo criar o main... com os animais vai dar erro nao e mesmo?

Anônimo disse...

Entendi a metodologia, mas no exemplo dado não seria melhor fazer assim:

Na classe animal:
public void som(String artigoMF, String nome, String numeroPatas, String som){
System.out.println(artigoMF + " " + nome + " que tem " + numeroPatas + " patas, faz " + som);
}

E nas classes Vaca e etc coloca seta apenas as String...
Estou começando agora e já prefiro tirar a dúvida...

Java Progressivo disse...

Claro, pode sim.
Não existem limites ou solução mais perfeita.

No caso desse tutorial, fizemos algo bem básico, pois estamos apresentando o assunto agora na apostila, é pra efeitos didáticos mesmo, e não tentando uma solução mais otimizada ou reduzida.

Anônimo disse...

Cadê a opção curtir? ;)
Parabéns!!

Rafael S. Gomes disse...

Muito bom !!! parabéns pelo trabalho !
Ficou muito simples, e fácil de entender :)

Marina Izumi disse...

Na aula achei um tanto confusa a ideia de abstrato, e do porque não haver declarações no método abstrato da super classe abstrata.
Agora ficou tudo mais claro.

Muito obrigada!!!

Anônimo disse...

Faz diferença usar o Abstract ? Se nas classes filhas o metodo som é override, eu poderia definir na classe pai que na filha mudaria cada uma. Não ?

Israel Araújo Guimarães disse...

Não tenho ânimo para ficar postando comentário em sites/blogs/etc não.

Mas se eu não agradecesse por esse site, seria muito injusto da minha parte!

FANTÁSTICO!!! Explicação de vocês é 10!

abraços!

Dinho Carvalho disse...

Cara excelente, estou lendo um livro da Caleum por sinal bom também, porém nem tudo é possível aprender com um livro, pesquiso sempre sobre as dúvidas, e numa boa, sempre começo por aqui, melhor site.

Dicas e Novidades de Java por e-mail

Sabe quanto custa um bom livro de java?
Entre R$ 100,00 e R$300,00

Sabe quanto custa um bom curso presencial de Java?
Entre R$ 1.500,00 até R$ 4.000,00

Sabe quanto custa estudar pelo Java Progressivo?
Absolutamente nada.

Porém, também precisamos de sua ajuda e apoio.
Para isso, basta curtir nossa Fan Page e clicar no botão G+ do Google.