sexta-feira, 4 de junho de 2010

Preparação para SCJP - Parte 2 (Classes Abstratas)

Classes abstratas
Chegamos à segunda parte do estudo. Falaremos de classes abstratas. Classes abstratas são tipos especiais de classe. Elas tem algumas características interessantes. A primeira delas e mais importante é que uma classe abstrata não pode ser instanciada! Elas servem somente para serem herdadas por outras classes! O seguinte código é inválido:

public abstract class ClasseAbstrata { }

public class ClasseConcreta {
    public static void main (String [] args){
        // Classes abstratas não podem ser instanciadas
        ClasseAbstrata ca = new ClasseAbstrata();
    }
}

Já esse é válido:

// Enquanto criar instancias é proibído, extender é algo totalmente válido!
public class ClasseConcreta extends ClasseAbstrata{
    
}

Um outro detalhe sobre classes abstratas é que elas podem conter métodos abstratos. Este detalhe é importante. Métodos abstratos só podem existir dentro de classes abstratas, porém uma classe abstrata pode conter métodos não abstratos (concretos). Discutiremos isso com detalhes depois. Vamos primeiro entender um método abstrato. Enquanto uma classe abstrata só serve para ser herdada (como visto anteriormente), métodos abstratos não fornecem uma implementação. São "métodos sem código". Quando declaramos um método abstrato, estamos dizendo que as classes concretas (não abstratas) que estenderem (herdarem) desta classe serão obrigados a implementar este método. A sintaxe de métodos abstratos também muda. Acompanhe o código abaixo:

public abstract class ClasseAbstrata { 
    public abstract void metodoAbstrato ();


public class ClasseConcreta extends ClasseAbstrata {
    public void metodoAbstrato (){
        // Implemente o código do método aqui.
    }


Observe que o método declarado como abstrato possui um ";" ao invés de "{}". Observe também que a classe que estendeu (herdou) a ClasseAbstrata é obrigada a fornecer uma implementação do método abstrato da classe "pai". Resumindo, quando declaramos um método abstrato não dizemos de forma alguma como ele deve se comportar. Deixamos o papel de fornecer implementação às classes "filhas". Caso uma classe subclassifique (herde) uma classe abstrata e não forneça implementação para todos os métodos abstratos da superclasse (classe pai) o compilador reclamará e devolverá um erro! Observe o mesmo código de antes:

public abstract class ClasseAbstrata { 
    public abstract void metodoAbstrato ();


public class ClasseConcreta extends ClasseAbstrata {
    // Vai dar erro quando tentar compilar esta classe. 
    // Só vai compilar quando for fornecida 
    // implementação para o método abstrato.
}

Existe ainda mais um aspecto a ser considerado por agora. Classes abstratas podem fornecer métodos abstratos! Observe:

public abstract class ClasseAbstrata { 
    public void metodoConcretoDeUmaClasseAbstrata () {
       //  Aqui vai um código bastante útil!!!
   }


public class ClasseConcreta extends ClasseAbstrata {
   


Neste caso, nenhum erro será retornado. A classe concreta herdará um método.Como o método não é abstrato, não é necessário fornecer implementação.

Classes abstratas são um tanto quanto chatas porque possuem diversas regras. Muitas delas foram faladas acima, mas ainda existem mais. Uma delas é que classes abstratas podem herdar de outras classes abstratas. Beleza, e daí? Daí que classes abstratas não tem nenhuma obrigação de fornecer implementação a nenhum método, mesmo que ele seja assinalado como abstrato na super classe. Porém esses métodos não podem ficar sem implementação. A primeira classe concreta que herdar será obrigada a implementar todos os métodos abstratos que foram declarados e ainda não foram implementados. Observe o código abaixo:

public abstract class ClasseAbstrataPai {
    public abstract void metodoAbstratoPai(); 
}

public abstract class ClasseAbstrataFilha extends ClasseAbstrataPai{
    // Não fornece implementação nenhuma
}

public class ClasseConcreta extends ClasseAbstrataFilha {
    public void metodoAstratoPai(){
        // Insira código útil aqui
    }
}

Se a classe "ClasseAbstrataFilha" tiver algum método abstrato, a classe concreta ainda é obrigada a implementá-lo. Tá complicado? Relaxa, que complica ainda mais. Se uma classe abstrata fornecer implementação a um dos métodos abstratos, a classe concreta passa a estar desobrigada a implementar os mesmos. Observe:

public abstract class ClasseAbstrataPai {
    public abstract void metodoAbstratoPai(); 
}

public abstract class ClasseAbstrataFilha extends ClasseAbstrataPai {
    // Implementa opcionalmente o método abstrato da classe pai
    public void metodoAstratoPai(){
        // Insira código útil aqui
    }
}


public class ClasseConcreta extends ClasseAbstrataFilha {
    // Não fornece implementação nenhuma.  
    // Não dá erro porque a classe pai já implementou o método.
}

Acredito que seja isso. Parece complexo e difícil de entender, mas quando você pega o jeito, vai embora! No próximo Post, Interfaces!
Bye dudes!

Nenhum comentário:

Postar um comentário