Desenvolvimento OO com Java Modificadores de acesso e atributos de classe Vítor E. Silva Souza ([email protected]) http://www.inf.ufes.br/~vitorsouza Departamento de Informática Centro Tecnológico Universidade Federal do Espírito Santo Licençaparausoedistribuição • EsteobraestálicenciadacomumalicençaCreative Commons Atribuição-CompartilhaIgual 4.0Internacional; • Vocêtemodireitode: – Compartilhar:copiareredistribuiromaterialem qualquersuporteouformato – Adaptar:remixar,transformar,ecriarapartirdo materialparaqualquerfim,mesmoquecomercial. • Deacordocomostermosseguintes: – Atribuição:vocêdevedarocréditoapropriado,proverumlinkpara alicençaeindicarsemudançasforamfeitas.Vocêdevefazê-loem qualquercircunstânciarazoável,masdemaneiraalgumaquesugira aolicencianteaapoiarvocêouoseuuso; – CompartilhaIgual:sevocêremixar,transformar,oucriarapartirdo material,temdedistribuirassuascontribuiçõessobamesma licençaqueooriginal. Mais informações podem ser encontradas em: http://creativecommons.org/licenses/by-sa/4.0/ Abril2016 OO&Java- Modif.deacessoeatributosdeclasse 2 Conteúdodocurso • OqueéJava; • Variáveisprimitivase controledefluxo; • Orientaçãoaobjetos básica; • Umpoucodevetores; • Modificadoresdeacesso eatributosdeclasse; • Herança,reescritae polimorfismo; • Classesabstratas; • Interfaces; • Exceçõesecontrolede erros; • UtilitáriosdaAPIJava. EstesslidesforambaseadosnaapostiladocursoFJ-11:Javae OrientaçãoaObjetosdaCaelum ena apostila Programação Orientada aObjetos em Javadoprof.Flávio MiguelVarejão. Abril2016 OO&Java- Modif.deacessoeatributosdeclasse 3 Questão deresponsabilidade (denovo!) • Imagineumsistema... – Dezenas deformulários; – CPFssão validados – função validar(cpf) deve ser chamada em cada formulário; – Todos osdesenvolvedoressão responsáveis! • Sem problemas!Define-seaclasse Pessoacomo atributo cpf eométodo validar()! – Eaí odesenvolvedor foi lá e… Pessoa p = new Pessoa(); p.cpf = "321.654.987-00"; // Cadê a validação? Abril2016 OO&Java- Modif.deacessoeatributosdeclasse 4 Regrasdenegócio • Paraumacontacorrente: class Conta { int numero; String dono; double saldo; double limite; // ... } RN1: quando negativo, o valor absoluto do saldo não pode ser superior ao do limite. Abril2016 OO&Java- Modif.deacessoeatributosdeclasse 5 Implementandoaregradenegócio class Conta { // Restante da classe... void sacar(double qtd) { double novoSaldo = this.saldo - qtd; this.saldo = novoSaldo; } } public class TesteConta { public static void main(String[] args) { Conta c = new Conta(); c.saldo = 1000.0; c.limite = 1000.0; c.sacar(5000); // Vai gerar inconsistência! } } Abril2016 OO&Java- Modif.deacessoeatributosdeclasse 6 Implementandoaregradenegócio public class TesteConta { public static void main(String[] args) { Conta c = new Conta(); c.saldo = 1000.0; c.limite = 1000.0; // Vamos verificar antes de sacar... double valorASacar = 5000.0; if (valorASacar < c.saldo + c.limite) c.sacar(valorASacar); } } A responsabilidade está com a classe certa? Abril2016 OO&Java- Modif.deacessoeatributosdeclasse 7 Implementandoaregradenegócio boolean sacar(double qtd) { double novoSaldo = this.saldo - qtd; if (novoSaldo >= -limite) { this.saldo = novoSaldo; return true; } else return false; } Conta c = new Conta(); c.saldo = 1000.0; c.limite = 1000.0; Conta TesteConta // Agora sim! if (c.sacar(5000)) System.out.println("Consegui"); else System.out.println("Não deu..."); c.saldo = -3000.0; Abril2016 // Só que não... OO&Java- Modif.deacessoeatributosdeclasse 8 Faltaencapsulamento... • Permitiroacessodiretoaos atributos: – Exige disciplina dosclientes daclasse Conta; – Pode levar ainconsistências; • Solução:impedir oacesso externo ao atributo: – Atributo privativo; – Externo =qualquer outra clase,exceto aproprietária doatributo (ex.:Conta paraoatributo saldo). • Vantagens: – Objetos trocam mensagens combaseem contratos; – Modificações na implementação não afetam clientes (ex.:adicionar CPMFnos saques deconta-corrente). Abril2016 OO&Java- Modif.deacessoeatributosdeclasse 9 Encapsulamento • Usamosobjetossemsaberseufuncionamento interno; • Assimtambém deveseremnossossistemasOO: – Maiormanutenibilidade; – Maiorreusabilidade. Abril2016 OO&Java- Modif.deacessoeatributosdeclasse 10 Implementando oencapsulamento class Conta { private int numero; private String dono; private double saldo; private double limite; public boolean sacar(double qtd) { // ... } // ... } Modificador de acesso / visibilidade! Abril2016 OO&Java- Modif.deacessoeatributosdeclasse 11 Modificadoresdeacesso • Determinamavisibilidade deumdeterminadomembro daclassecomrelação aoutrasclasses; • Háquatro níveisdeacesso: – Público (public); – Privado/privativo (private); – Protegido (protected); – Amigo ouprivativoaopacote(friendly oupackageprivate). Regra de bolso do encapsulamento: atributos são privativos, métodos são públicos. Regra de bolso das regras: toda regra tem suas exceções… Abril2016 OO&Java- Modif.deacessoeatributosdeclasse 12 Palavras-chave • Três palavras-chaveespecificamoacesso: – public – private – protected • Oníveldeacessopackage-private édeterminadopela ausência deespecificador; • Devemserusadasantes donomedomembro que queremespecificar; • Nãopodemserusadasemconjunto. Abril2016 OO&Java- Modif.deacessoeatributosdeclasse 13 Modificadoresdeacesso Acesso Público Protegido Amigo Privado A própria classe Sim Sim Sim Sim Classe no mesmo pacote Sim Sim Sim Não Subclasse em pacote diferente Sim Sim Não Não Não-subclasse em pacote diferente Sim Não Não Não Abril2016 OO&Java- Modif.deacessoeatributosdeclasse 14 Testando oencapsulamento class Conta { // ... private double saldo; Conta public boolean sacar(double qtd) { // ... } } Conta c = new Conta(); c.depositar(1000.0); c.saldo = -3000.0; TesteConta // Não compila! // error: saldo has private access in Conta // c.saldo = -3000.0; // ^ Abril2016 OO&Java- Modif.deacessoeatributosdeclasse 15 Separandointerfaceeimplementação • EmOOéfundamental oocultamento deinformação: – Estruturainterna ficainacessível; – Interface doobjetoépública. • Oqueéumapilha? – Umalista? – Umvetor? – Umaestrutura quemepermiteempilhar e desempilhar itens? Abril2016 OO&Java- Modif.deacessoeatributosdeclasse 16 Ocultamentodeinformações import java.util.*; class Pilha { private Vector elems; public Pilha() { elems = new Vector(10, 10); } public void empilha(Object obj) { elems.add(obj); } public Object desempilha() { Object obj = elems.get(elems.size() - 1); elems.remove(elems.size() - 1); return obj; } } Abril2016 OO&Java- Modif.deacessoeatributosdeclasse 17 Mudandoaimplementação import java.util.*; class Pilha { private LinkedList elems; public Pilha() { elems = new LinkedList(); } public void empilha(Object obj) { elems.addFirst(obj); } public Object desempilha() { return elems.removeFirst(); } } Programe para interfaces, não para implementações! (Design Patterns, de Eric Gamma et al.) Abril2016 OO&Java- Modif.deacessoeatributosdeclasse 18 OexemplodoCPF class Cliente { private String nome; private String endereco; private String cpf; private int idade; public void mudaCPF(String cpf) { validaCPF(cpf); this.cpf = cpf; } private void validaCPF(String cpf) { // série de regras aqui, falha caso não seja válido } // ... } Abril2016 E se um dia eu não precisar mais validar CPF para pessoas com idade acima de 60 anos? OO&Java- Modif.deacessoeatributosdeclasse 19 Maseseeu precisar acessar umatributo? • Bastausarummétodo paraisso! class Conta { int numero; String dono; double saldo; double limite; public double verSaldo() { return saldo; } public void alterarLimite(double limite) { this.limite = limite; } // ... } Abril2016 OO&Java- Modif.deacessoeatributosdeclasse 20 POJOs (oBom eVelhoObjeto Java) • Atributosdevemserprivativos; • Seprecisaremserlidos oualterados,provermétodos get/set(parabooleanos,pode-seusaroprefixois): public class Cliente { // ... private String nome; public String getNome() { return nome; } public void setNome(String nome) { this.nome = nome; } IDEs geram esses métodos } automaticamente. Abril2016 OO&Java- Modif.deacessoeatributosdeclasse 21 Planeje bem ainterfacedaclasse • É importante observar que: – Ométodo getAtr() não temque necessariamente retornar apenas oatributo atr; – Não crie automaticamente métodos get/setpara todos os atributos!Paraalguns não faz sentido… // O limite faz parte do saldo (só que cobra juros)! public double getSaldo() { return saldo + limite; } // Não há método para mudar o saldo. Tem que sacar() // public void setSaldo(double saldo) Sugestão de leitura: http://blog.caelum.com.br/nao-aprender-oo-getters-e-setters/ Abril2016 OO&Java- Modif.deacessoeatributosdeclasse 22 Inicialização • Neologismocriadoparaindicartarefas quedevemser efetuadasaoiniciarmos algo; • Quandocriamosobjetos,podemosquererinicializá-lo comalgunsvalores; • Poderíamoscriarummétodo paraisso: class Aleatorio { private int numero; public void inicializar() { Random rand = new Random(); numero = rand.nextInt(20); } } Abril2016 OO&Java- Modif.deacessoeatributosdeclasse 23 Construtores • Problema dométodoinicializar(): podemos esquecer dechamá-lo! • Porisso,Javaprovêomecanismodeconstrutores: – São chamadosautomaticamente peloJavaquando umobjetonovoécriado; – Construtoresnão tem valorderetornoepossuemo mesmo nomedaclasse. new → construtor Abril2016 OO&Java- Modif.deacessoeatributosdeclasse 24 Construtores • Quandoumnovo objetoécriado: 1. éalocadamemória paraoobjeto; 2. oconstrutor échamado. class Aleatorio { private int numero; public Aleatorio() { Random rand = new Random(); numero = rand.nextInt(20); } } public class Teste { public static void main(String[] args) { Aleatorio aleat = new Aleatorio(); } } Abril2016 OO&Java- Modif.deacessoeatributosdeclasse 25 Construtorespodemterargumentos • Sedefinidosargumentos,devemserpassadosna criação doobjetocomnew: class Aleatorio { private int numero; public Aleatorio(int max) { Random rand = new Random(); numero = rand.nextInt(max); } } public class Teste { public static void main(String[] args) { Aleatorio aleat1 = new Aleatorio(20); Aleatorio aleat2 = new Aleatorio(50); } } Abril2016 OO&Java- Modif.deacessoeatributosdeclasse 26 Podehavermúltiplosconstrutores • Nossasclassespodemterquantos construtores quisermos (comargumentosdiferentes): class Aleatorio { private int numero; public Aleatorio() { Random rand = new Random(); numero = rand.nextInt(20); } public Aleatorio(int max) { Random rand = new Random(); numero = rand.nextInt(max); } } public class Teste { public static void main(String[] args) { Aleatorio aleat1 = new Aleatorio(); Aleatorio aleat2 = new Aleatorio(50); } Abril2016 OO&Java- Modif.deacessoeatributosdeclasse 27 Construtordefault • Quandonão especificamosconstrutores,Javaprovêum construtordefault paranossaclasse: – Todaclasseprecisa deumconstrutor; – Semparâmetros esemimplementação. • Quandoespecificamos construtores,oconstrutor default não éprovidoautomaticamente: – Sevocêescreveu umconstrutor,Javaassumeque vocêsabe oqueestáfazendoenãoprovêum; – Chamar oconstrutorsemoparâmetrogeraerro se elenãofordefinidoexplicitamente. Isso é bom! Mas por que? (Apostila Caelum, sec. 6.5) Abril2016 OO&Java- Modif.deacessoeatributosdeclasse 28 Construtoreschamandoconstrutores • Seriainteressante nãohaverduplicação decódigo: class Aleatorio { private int numero; public Aleatorio() { Random rand = new Random(); numero = rand.nextInt(20); } public Aleatorio(int max) { Random rand = new Random(); numero = rand.nextInt(max); } } Abril2016 OO&Java- Modif.deacessoeatributosdeclasse 29 Construtoreschamandoconstrutores • Usamosnovamente apalavra-chavethis,comoutro significado:chamaroutroconstrutor: class Aleatorio { private int numero; public Aleatorio() { // Chama o outro construtor com argumento 20. this(20); } public Aleatorio(int max) { Random rand = new Random(); numero = rand.nextInt(max); } } Abril2016 OO&Java- Modif.deacessoeatributosdeclasse 30 Construtoreschamandoconstrutores • Achamadathis(): – Deveespecificarosargumentos doconstrutoraser chamado; – Deveseraprimeira linhadoconstrutorqueautiliza; – Nãopodeserusadaforadeconstrutores. Depois que o objeto foi construído, não é mais possível chamar o construtor para ele. Abril2016 OO&Java- Modif.deacessoeatributosdeclasse 31 Opadrão JavaBean Abril2016 OO&Java- Modif.deacessoeatributosdeclasse 32 DesenvolvimentoOOcomJava– Modific.deacessoeatributosdeclasse ATRIBUTOSDECLASSE Abril2016 OO&Java- Modif.deacessoeatributosdeclasse 33 Atributos independentes deobjetos • Vimosatéagoraqueatributos pertencemaosobjetos: – Nãosefaznadasemantescriar umobjeto(new)! • Noentanto,hásituações quevocêquerusá-lossem ter quecriarobjetos: public class TesteConta { public static void main(String[] args) { int qtdContas = 0; Conta c1 = new Conta(); qtdContas++; Conta c2 = new Conta(); qtdContas++; // ... } } Abril2016 A responsabilidade está com a classe certa? OO&Java- Modif.deacessoeatributosdeclasse 34 Atributos independentes deobjetos • Seacertamos aresponsabilidade,voltamos adepender deumobjeto parausar oatributo: class Conta { // ... public int qtdContas = 0; public Conta() { qtdContas++; } // Outras inicializações... } Conta c1 = new Conta(); Conta c2 = new Conta(); TesteConta // Quantas contas foram criadas? System.out.println(c2.qtdContas); Abril2016 OO&Java- Modif.deacessoeatributosdeclasse 35 Atributosstatic • Usandoapalavra-chavestatic vocêdefineum atributodeclasse(“estático”): – Pertenceàclasse comoumtodo; – Pode-seacessá-losmesmosemtercriado umobjeto; – Objetospodem acessá-loscomosefosseum membrodeobjeto,sóquecompartilhado. class Conta { // ... public static int qtdContas = 0; public Conta() { qtdContas++; } // Outras inicializações... } Abril2016 OO&Java- Modif.deacessoeatributosdeclasse 36 Acesso aatributos static • Não precisamos mais deumobjeto pra acessar: public class TesteConta { public static void main(String[] args) { Conta c1 = new Conta(); Conta c2 = new Conta(); System.out.println(Conta.qtdContas); // ... } } O atributo é da classe. A visibilidade está certa? Abril2016 OO&Java- Modif.deacessoeatributosdeclasse 37 Acesso aatributos static • Seacertamos avisibilidade doatributo,precisamos então deummétodo paraacessá-lo: class Conta { // ... private static int qtdContas = 0; public Conta() { qtdContas++; } // Outras inicializações... public int getQtdContas() { return qtdContas; } } Mas não sendo static, vou precisar de um objeto pra acessar o atributo de novo!?! Abril2016 OO&Java- Modif.deacessoeatributosdeclasse 38 Métodos static • Métodos também podem ser static: class Conta { // ... private static int qtdContas = 0; public Conta() { qtdContas++; /* ... */ } public static int getQtdContas() { return qtdContas; } } Conta c1 = new Conta(); Conta c2 = new Conta(); TesteConta // Quantas contas foram criadas? System.out.println(Conta.getQtdContas()); Abril2016 OO&Java- Modif.deacessoeatributosdeclasse 39 Armazenamentoemmemória Classe Conta qtdContas = 2 sacar() depositar() saldo = 1_000_000_000 meuSonho minhaConta Março2016 saldo = 1_000 OO&Java- Orientaçãoaobjetosbásica 40 Contexto static • Métodos staticnão podem acessar membros não-static: public class Teste { private int atributo; private int atributoStatic; public void metodo() { } public static void metodoStatic() { } public static void main(String[] args) { // ... System.out.println(atributoStatic); System.out.println(Teste.atributoStatic); metodoStatic(); Teste.metodoStatic(); // Continua... Abril2016 OO&Java- Modif.deacessoeatributosdeclasse 41 Contexto static // // // // // Não pode: System.out.println(atributo); System.out.println(Teste.atributo); metodo(); Teste.metodo(); // Preciso de um objeto: Teste t = new Teste(); System.out.println(t.atributo); t.metodo(); } } Abril2016 OO&Java- Modif.deacessoeatributosdeclasse 42 Cuidadocomostatic • Membrosestáticos são como variáveis/funções globais; • Sãomais procedurais doque orientados aobjetos; • Noentanto,em alguns casos são necessários… Abril2016 OO&Java- Modif.deacessoeatributosdeclasse 43 Exercitar é fundamental • ApostilaFJ-11daCaelum: – Seção 6.8,página 81(classFuncionario); – Seção 6.9,página 83(desafios). Abril2016 OO&Java- Modif.deacessoeatributosdeclasse 44 http://nemo.inf.ufes.br/