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