Modificadores de acesso e atributos de classe Material baseado na apostila FJ-11: Java e Orientação a Objetos do curso Caelum, Ensino e Inovação, disponível para download em http://www.caelum.com.br/apostilas/ 1 Objetivos • Controlar o acesso aos métodos, atributos e construtores das classes através dos modificadores private e public; • Escrever métodos de acesso a atributos do tipo getters e setters; • Escrever construtores para suas classes; • Utilizar variáveis e métodos estáticos. 2 Controlando o acesso • Vamos voltar à classe Conta e observar o seu método saca( ). 3 Controlando o acesso • O problema consiste em que o método saca() não impede que a retirada ultrapasse o limite da conta. 4 Controlando o acesso • Poderíamos colocar um if no método saca() para evitar o estouro do limite... 5 Controlando o acesso • Mas o que garante que os usuários da classe (os programadores vermelhos) vão sempre usar o método saca() para efetuar retiradas? 6 Controlando o acesso • Como evitar o estouro da conta? Os programadores vermelhos (os usuários da classe Conta) poderiam acrescentar um if ao seu código. 7 Controlando o acesso • Problemas com essa solução: – O que garante que os programadores vermelhos irão se lembrar de fazer o teste? – Esse mesmo teste pode ter de ser repetido em vários lugares diferentes do código. – A verificação das regras de negócio da classe Conta não deveria ser responsabilidade dos usuários da classe (programadores vermelhos), mas sim do programador que escreveu a classe Cliente (programador azul) 8 Controlando o acesso • A melhor solução seria então forçar os programadores usuários da classe (programadores vermelhos) a usar o método saca(), e impedi-los de acessar diretamente os atributos da classe. • Para fazer isso, basta preceder a declaração dos atributos com a palavra reservada private 9 Controlando o acesso • qualquer tentativa por parte dos usuários da classe (programadores vermelhos) de acessar diretamente um atributo private, irá resultar em um erro de compilação. 10 Encapsulamento • A prática (do programador azul) de proteger a integridade da classe escondendo certas informações dos usuários dessa classe (programadores vermelhos) e mostrando somente aquilo que é necessário para a utilização da classe é chamada de encapsulamento. • Devemos sempre expor o mínimo possível de funcionalidades para criar um baixo acoplamento entre as classes do projeto • Vantagens do encapsulamento – Os usuários da classe sabem o que ela faz, mas não como ela faz. Isso permite ao programador da classe (programador azul) alterar a implementação de métodos ou introduzir/modificar novas regras de negócio, sem afetar o código escrito pelos programadores usuários da classe (programadores vermelhos). 11 Modificadores de acesso • Além do modificador de visibilidade private, temos também o modificador public que permite o acesso irrestrito a atributos e métodos. 12 Dicas de codificação • Em geral, atributos são privados e métodos são públicos. • Podem haver no entanto, exceções a essa regra. • O conjunto de métodos públicos de uma classe é chamado de interface da classe, pois esta é a única maneira pela qual é possível se comunicar com os objetos dessa classe. 13 Interfaces • Ao escrever seus programas, os programadores vermelhos devem se concentrar nas interfaces das classes escritas pelos programadores azuis. • Em outras palavras, os programadores vermelhos devem se concentrar NO QUE as classes fazem e não em COMO elas fazem. 14 Interfaces - Analogia • O conceito de utilizar interfaces de serviços é corriqueiro no nosso dia a dia: – Utilizamos a interface de um automóvel (o volante, os pedais, a alavanca de câmbio) sem precisar saber como funciona um automóvel. – Utilizamos a interface de uma televisão (o controle remoto) sem precisar saber como funciona uma televisão. – Utilizamos a interface de uma pizzaria (o telefone) para pedir uma pizza e não sabemos se o forno é a gás ou lenha, como se chama o pizzaiolo ou quanto ele ganha. 15 O problema original: validação de CPF Uma vez que o atributo cpf é privado, a única forma de alterá-lo é através do método mudaCPF() → consequencia: é impossível armazenar um cpf inválido. 16 Getters e Setters • O método mudaCPF() no exemplo anterior é chamado de um setter, isto é, um método que tem a responsabilidade de alterar o atributo privado de uma classe. • Vamos voltar à classe Conta e escrever um método de acesso para leitura (um getter) e um método de acesso para escrita (um setter) do atributo limite. 17 Getters e Setters 18 Getters e Setters • Você poderia dar ao getter e ao setter os nomes que quisesse. Você poderia, por exemplo, chamá-los de leiaLimite() e escrevaLimite(). • Essa não parece ser, no entanto, uma boa idéia. Os nomes getXXX() e setXXX() são por demais usuais. Além disso, se você pedir ao NetBeans para criar para você os métodos de acesso (Alt + Insert) ele os criará com os nomes getXXX() e setXXX() • O método getXXX() não retorna necessariamente o valor do atributo XXX. Observe o exemplo a seguir onde o método getSaldo() retorna o saldo do cliente acrescido do limite de crédito (uma prática comum dos bancos). 19 Getters e Setters 20 Métodos Construtores • Quando usamos a palavra reservada new para criar uma nova instância de uma classe (um objeto), estamos em verdade invocando o método construtor dessa classe. método construtor o operador new a referência para o novo objeto a classe como um tipo • O método construtor é um método que tem, obrigatoriamente, o mesmo nome da classe. 21 Métodos Construtores • O método construtor é um método especial, que é executado toda vez que uma nova instância é criada. • Sua função é definir o estado inicial (o valor dos atributos) da instância recém criada. 22 O construtor padrão • Até agora, não escrevemos em nossas classes nenhum método construtor. Como então foi possível criar instâncias de classes usando o new? • Se você não escrever seu próprio construtor, o compilador cria para você um construtor padrão • Esse construtor não recebe parâmetros e não contém nenhuma instrução dentro do abre e fecha chaves. Sua função é simplesmente “estar lá”, já que é necessário haver um construtor para a criação de instâncias. 23 O construtor padrão 24 Métodos Construtores • Os construtores podem receber parâmetros e, assim, inicializar os atributos com valores passados pelos usuários da classe (programadores vermelhos) 25 Métodos Construtores • No exemplo anterior, o método construtor recebe o cliente titular da conta. Assim, quando criarmos uma nova conta ela já terá um titular. 26 A necessidade de um construtor • Por que devo criar meus próprios construtores se o compilador me fornece um construtor default? 1. Para forçar os usuários da classe (programadores vermelhos) a fornecer os parâmetros obrigatórios de inicialização do objeto. Lembre-se, quando você escreve seus próprios construtores o construtor padrão não mais é fornecido, então, se você escrever um construtor que recebe parâmetros, novas instâncias dessa classe só poderão ser criadas se esses parâmetros forem fornecidos. 2. Para facilitar a vida dos programadores vermelhos. Talvez fosse possível, em alguns casos, deixar os programadores vermelhos criarem instâncias da classe usando o construtor padrão (com todos os atributos zerados) e, depois, definirem o estado desses objetos usando os setters, mas isso definitivamente seria mais trabalhoso. 27 Sobrecarga de métodos construtores 28 Sobrecarga de métodos construtores 29 Usando Construtores • Exemplo de uso desses métodos construtores: 30 Atributos de classe 31 Atributos de classe • Suponha que nosso banco precisa saber, a qualquer momento, o número de contas já abertas. Uma solução para isso seria: 32 Atributos de classe • Essa solução tem um problema muito parecido com a validação de CPF. O código para incrementar o número total de contas pode estar espalhado por vários lugares da aplicação. Além disso, não há como garantir que os usuários da classe vão se lembrar de incrementar a variável totalDeContas. Resumindo, o problema dessa solução está em que a responsabilidade de manter o número total de contas está com os programadores vermelhos (usuários da classe) quando deveria estar com o programador azul (autor da classe). • Poderíamos então pensar na seguinte solução: não funciona!!! 33 Atributos de classe • O problema está em que o número total de contas é um atributo da conta, assim como o saldo ou o limite e cada instância criada teria o seu próprio contador de contas que será sempre incrementado de zero para um. • Precisamos então de uma espécie de variável global a todas as instâncias da classe, isto é, uma variável única para todas as instâncias. • Essa variável global é obtida com a palavra reservada static. a variável totalDeContas é chamada de uma variável de classe enquanto que as variáveis saldo e limite são chamadas de variáveis de instância 34 Atributos de classe • Deveríamos usar os princípios do encapsulamento e transformar o atributo totalDeContas em um atributo privado e, em seguida, escrever um getter para o mesmo. 35 Atributos de classe • Como os usuários da classe podem agora ter acesso a essa informação? • Existe ainda um problema com essa solução. Para saber o número total de contas é preciso haver ao menos uma conta já instanciada. Como obter a informação de que nenhuma conta foi ainda aberta? Solução: métodos de acesso a variáveis estáticas são, em geral, também eles estáticos. 36 Métodos estáticos • Que podem ser acessados como: observe a referência através de uma classe e não de uma instância 37 Pense nisso... • Um método estático não pode acessar atributos de instância. Por que? 38