terça-feira, 8 de junho de 2010

Preparação para SCJP - Parte 3 (Interfaces)

Vamos ao próximo post: Interfaces.

Interfaces são classes abstratas por padrão. Sendo assim, não existe a necessidade de declará-la como tal. Porém, declará-la como abstract (apesar de redundante) é válido. Observe as seguintes declarações:

public abstract interface MinhaInterface { }


public interface MinhaInterface { }

Ambas declarações são válidas. Mas afinal de contas, o que raios é uma interface? Interface, é uma forma de você obrigar uma classe a se comportar de determinada forma. Como assim? Vamos entender por partes. Em primeiro lugar, a interface é um pouco mais que uma classe abstrata. É uma classe abstrata que possui somente métodos abstratos e públicos (mesmo que você não os declare como tal). Todos os atributos que você declarar em uma interface serão constantes, ou seja, não existem variáveis de instância em uma interface. Acompanhe o exemplo de declaração de métodos:

public interface MinhaInterface {
    public abstract void meuPrimeiroMetodo();
    // Se declarasse como abaixo também estaria correto:
    abstract void meuPrimeiroMetodo();
    // Assim também está certo:
    void meuPrimeiroMetodo();
}
Veja a declaração de atributos:
public interface MinhaInterface{
    public static final int constanteDeInterface = 20;
    // Os códigos abaixo declaram constantes, mesmo que não esteja explícito, e são todos válidos!
    public int constanteDeInterface = 20;


    static int constanteDeInterface = 20;
    final int constanteDeInterface = 20;
    public static int constanteDeInterface = 20;
    public final int constanteDeInterface = 20;
    static final int constanteDeInterface = 20;
}

Como dito anteriormente, interfaces são implicitamente classes abstratas. Sendo assim, não pode ser instanciada. Porém, diferente do que acontece com classes abstratas, interfaces não são extensíveis (exceto por outras interfaces), e sim implementáveis. Ao invés de usar a palavra chave "extends", utiliza-se "implements". Diferentemente do conceito de herança, uma classe pode implementar mais de uma interface. Veja os exemplos:

public interface MinhaInterface { }


// Implementação válida de uma interface
public class ClasseConcreta implements MinhaInterface { }


// O seguinte também é válido:
public class ClasseConcreta implements MinhaInterface, Runnable { }

// Uma interface pode extender de outra interface, 
// mas nunca implementar!
public interface OutraInterface extends MinhaInterface { }

Interfaces são também uma maneira de simular mútipla herança, já que por bons motivos, a linguagem não possui suporte a este recurso. Uma classe abstrata também pode implementar uma interface, mas isso implica em fornecer implementação aos métodos da interface (que são inerentemente abstratos). Como a classe é abstrata, ela pode optar por delegar a implementação dos métodos abstratos dela própria e da interface à próxima classe concreta. Acompanhe o exemplo:

public interface Pulador {
    // Lembre-se que métodos abstratos terminam 
    // com ";" e não "{}"!
    void pular();
}


// Observe que o fato de implementar uma interface não impede de extender outra classe!
public abstract class Pneu extends Borracha implements Pulador {
    public abstract void rodar ();
    // Perceba que a classe optou por não implementar o método pular.
    // Isso é totalmente válido, pois é uma classe abstrata.
}

public class PneuDeCaminhao extends Pneu {
    /* Essa classe, por ser concreta e herdar de Pneu é 
     * obrigada a fornecer implementação de todos os 
     * métodos abstratos que ainda não tem implementação. 
     * Tanto da interface quanto da classe abstrata que ele 
     * herda diretamente*/
    public void rodar() { 
        // Código útil aqui 
    }
    
    public void pular() {
        // Código útil aqui
    }
}

Como mostrado anteriormente, interfaces também utilizam herança. Interfaces NUNCA poderão implementar outra interface. Observe os exemplos:

public interface InterfacePai {
    void metodoDaInterfacePai ( );
}


// Este código é válido!
public interface InterfaceFilha extends InterfacePai{
    void metodoDaInterfaceFilha ( );
}


// Este código é inválido!


public interface InterfaceFilha implements InterfacePai{
    void metodoDaInterfaceFilha ( );
}


// Este código é válido!


public interface InterfaceFilha extends InterfacePai{
    void metodoDaInterfaceFilha ( );
    void metodoDaInterface
}

Bom, acho que tem bastante informação aí. É isso. Até mais!!! See you guys!!!

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!

quinta-feira, 3 de junho de 2010

Preparação para SCJP - Parte 1

Modificadores de acesso a classes:

Começaremos as discussões sobre a SCJP com este tópico:
Existem certos tópicos da linguagem Java que por não serem amplamente utilizados acabam sendo esquecidos pelos desenvolvedores. O problema é que estes tópicos são explorados nas provas de certificação da Sun. Um destes tópicos é justamente os modificadores de acesso das classes. Digo isso porque a maioria das classes tem o modificador de acesso "public". Mas este é o único modificador de acesso possível a uma classe? A resposta é não. Existe o modificador default que também pode ser atribuído a uma classe. Mas como isso funciona?

Modificador de acesso é uma forma que a linguagem Java tem de restringir o acesso a determinadas partes de código. Em classes, quer dizer que se pode restringir ou liberar acesso para que outras classes possam acessá-la através de instâncias ou herança (esses assuntos serão discutidos em outro post). Para classes existem dois modificadores aceitáveis:
-Public: modificador mais comum. Classes assinaladas com este modificador podem ser utilizadas por qualquer classe dentro do universo Java. Em cada arquivo ".java" só poderá existir uma classe public. Exemplo de sintaxe:

public class ClassePublica {
     // insira implementação da classe aqui
}

-Default: este modificador é mais restritivo que o modificador public. Ele diz que apenas as classes que estiverem no mesmo pacote que esta classe poderão ter acesso a ela. Exemplo de sintaxe:

class ClasseDefault {
     // insira implementação da classe aqui
}

Vamos desenhar um contexto:
Imagine que seu projeto tem dois pacotes: pacotea e pacoteb. Dentro do pacote "pacotea" criaremos duas classes: ClassePublica e ClasseDefault. Dentro do pacote "pacoteb", criaremos a classe "Main" e tentaremos fazer acesso às classes presentes no "pacotea". Acompanhe o código abaixo:

// Classe  pública dentro do pacotea
package pacotea;

public class ClassePublica {

}



// Classe com acesso default dentro do pacoteb
package pacotea;
// Note a ausência de um modificador de acesso. Indica modificador default!
class ClasseDefault {

}



// Classe que implementa uma instância de cada classe. Está em outro pacote.
package pacoteb;
// Note que esta classe está importando todas as classes do pacotea
import pacotea.*;

public class Main {

    public static void main(String[] args) {

        // Cria uma instância da classe com modificador público
        ClassePublica cp = new ClassePublica();

        // Tenta criar uma instância da classe com modificador default.
        ClasseDefault cd = new ClasseDefault();
    }

}



Caso você tente rodar este código, o compilador reclamará e exibirá um erro como este:
"The type ClasseDefault is not visible".

Agora, tente alterar o modificador de acesso da ClasseDefault para public e compile o projeto novamente. O erro desaparecerá!

Para desenvolvedores mais experientes, pode parecer bobo, mas é uma ótima pegadinha dentro de uma prova!

Pronto. Parte 1 concluída. Próximo post será sobre classes abstratas. See you guys!!!

Como se preparar para SCJP

É fato que todo desenvolvedor sonha em ter uma certificação. Se ela for bem vista no mercado passa a ser meta dos mesmos. Foi pensando dessa forma que eu decidí tirar a minha certificação SCJP. Iniciei meus estudos a duas semanas e ainda vou levar mais oito pra fazer a prova. Vou colocar aqui no blog meus progressos pra que outros tenham melhor chance. Estou seguindo o livro da Kathy Sierra e Bert Bates (Guia de Estudo SCJP) e recomendo. O livro abrange todos os tópicos referentes à certificação e te dá uma preparação que dispensa qualquer curso por aí. De quebra, o livro ainda traz mais de 280 questões e dois master exams. Vamos ao que interessa. Como se preparar para a certificação?

Eu acredito que em tudo que se for fazer na vida é necessário planejamento e organização. Estudar não é diferente. Então, eu definí um plano de estudo bem elaborado e com um objetivo ao final. Meu plano de estudo foi feito com base no livro da Kathy Sierra. O livro é dividido em dez capítulos. Eu decidí que leria um capítulo por semana, faria os exercícios do capítulo no sábado e revisaria o conteúdo no domingo. Isso me dá cerca de dez páginas por dia. Parece pouco, mas eu trabalho e estudo! Bom, já tenho meu plano, prazos a cumprir e etc. Agora é só colocar em prática (que é o que estou fazendo!). Durante esse período de estudo eu vou estar postando algumas considerações interessantes que eu for tirando do livro. Acredito que vá ajudar quem ler o blog e também a mim, afinal a melhor maneira de fixar o aprendizado é ensinando. Me despesso por aqui. Até o próximo post.