Important Announcement
PubHTML5 Scheduled Server Maintenance on (GMT) Sunday, June 26th, 2:00 am - 8:00 am.
PubHTML5 site will be inoperative during the times indicated!

Home Explore caelum-java-objetos-fj11

caelum-java-objetos-fj11

Published by Claudivan, 2018-03-18 10:22:17

Description: Java - Orientação a Objetos - Curso FJ-11

Search

Read the Text Version

.6. Use o Control + Shift + F para formatar o seu código. Dessa maneira, ele vai arrumar a bagunça de espaçamento e enters do seu código.7. (opcional) O que são os arquivos .project e .classpath? Leia o conteúdo deles.8. (opcional) Clique da direita no projeto, propriedades. É uma das telas mais importantes do Eclipse, onde você pode configurar diversas informações para o seu projeto, como compilador, versões, formatador e outros.

.6.9 DISCUSSÃO EM AULA: REFACTORING Existe um menu no Eclipse chamado Refactor. Ele tem opções bastante interessantes para auxiliar naalteração de código para melhorar organização ou clareza. Por exemplo, uma de suas funcionalidades étornar possível mudar o nome de uma variável, método ou mesmo classe de forma que uma alteração(em um lugar só do sistema) atualize todas as outras vezes que usavam o nome antigo. Usar bons nomes no seu código é um excelente começo para mantê-lo legível e fácil de darmanutenção! Mas o assunto \"Refatoração\" não para por aí: quebrar métodos grandes em menores,dividir classes grandes em algumas pequenas e mais concisas, melhorar o encapsulamento... todas essassão formas de refatoração. E esse menu do Eclipse nos ajuda a fazer várias delas.

.CAPÍTULO 7PACOTES - ORGANIZANDO SUASCLASSES E BIBLIOTECAS\"Uma discussão prolongada significa que ambas as partes estão erradas\" -- Voltaire Ao término desse capítulo, você será capaz de: separar suas classes em pacotes; preparar arquivos simples para distribuição.7.1 ORGANIZAÇÃO Quando um programador utiliza as classes feitas por outro, surge um problema clássico: comoescrever duas classes com o mesmo nome? Por exemplo: pode ser que a minha classe de Data funcione de um certo jeito, e a classe Data deum colega, de outro jeito. Pode ser que a classe de Data de uma biblioteca funcione ainda de umaterceira maneira diferente. Como permitir que tudo isso realmente funcione? Como controlar quem quer usar qual classe de Data ? Pensando um pouco mais, notamos a existência de um outro problema e da própria solução: osistema operacional não permite a existência de dois arquivos com o mesmo nome sob o mesmodiretório, portanto precisamos organizar nossas classes em diretórios diferentes. Os diretórios estão diretamente relacionados aos chamados pacotes e costumam agrupar classes defuncionalidades similares ou relacionadas. Por exemplo, no pacote java.util temos as classes Date , SimpleDateFormat e GregorianCalendar ; todas elas trabalham com datas de formas diferentes.

. Agora é a melhor hora de respirar mais tecnologia! Se você está gostando dessa apostila, certamente vai aproveitar os cursos online que lançamos na plataforma Alura. Você estuda a qualquer momento com a qualidade Caelum. Programação, Mobile, Design, Infra, Front-End e Business! Ex-aluno da Caelum tem 15% de desconto, siga o link! Conheça a Alura Cursos Online.7.2 DIRETÓRIOS Se a classe Cliente está no pacote contas , ela deverá estar no diretório com o mesmo nome: contas . Se ela se localiza no pacote br.com.caelum.contas , significa que está no diretório br/com/caelum/contas . A classe Cliente , que se localiza nesse último diretório mencionado, deve ser escrita da seguinteforma: package br.com.caelum.contas; class Cliente { // ... } Fica fácil notar que a palavra chave package indica qual o pacote/diretório contém esta classe. Um pacote pode conter nenhum ou mais subpacotes e/ou classes dentro dele.

. PADRÃO DA NOMENCLATURA DOS PACOTES O padrão da sun para dar nome aos pacotes é relativo ao nome da empresa que desenvolveu a classe: br.com.nomedaempresa.nomedoprojeto.subpacote br.com.nomedaempresa.nomedoprojeto.subpacote2 br.com.nomedaempresa.nomedoprojeto.subpacote2.subpacote3 Os pacotes só possuem letras minúsculas, não importa quantas palavras estejam contidas nele. Esse padrão existe para evitar ao máximo o conflito de pacotes de empresas diferentes. As classes do pacote padrão de bibliotecas não seguem essa nomenclatura, que foi dada para bibliotecas de terceiros.7.3 IMPORT Para usar uma classe do mesmo pacote, basta fazer referência a ela como foi feito até agorasimplesmente escrevendo o próprio nome da classe. Se quisermos que a classe Banco fique dentro dopacote br.com.caelum.contas , ela deve ser declarada assim: package br.com.caelum.contas; class Banco { String nome; } Para a classe Cliente ficar no mesmo pacote, seguimos a mesma fórmula: package br.com.caelum.contas; class Cliente { String nome; String endereco; } A novidade chega ao tentar utilizar a classe Banco (ou Cliente ) em uma outra classe que estejafora desse pacote, por exemplo, no pacote br.com.caelum.contas.main : package br.com.caelum.contas.main; class TesteDoBanco { public static void main(String[] args) { br.com.caelum.contas.Banco meuBanco = new br.com.caelum.contas.Banco(); meuBanco.nome = \"Banco do Brasil\"; System.out.println(meuBanco.nome); } }

. Repare que precisamos referenciar a classe Banco com todo o nome do pacote na sua frente. Esse éo conhecido Fully Qualified Name de uma classe. Em outras palavras, esse é o verdadeiro nome de umaclasse, por isso duas classes com o mesmo nome em pacotes diferentes não conflitam. Mesmo assim, ao tentar compilar a classe anterior, surge um erro reclamando que a classe Banco não está visível. Acontece que as classes só são visíveis para outras no mesmo pacote e, para permitir que a classe TesteDoBanco veja e acesse a classe Banco em outro pacote, precisamos alterar essa última etransformá-la em pública: package br.com.caelum.contas; public class Banco { String nome; } A palavra chave public libera o acesso para classes de outros pacotes. Do mesmo jeito que ocompilador reclamou que a classe não estava visível, ele reclama que o atributo/variável membrotambém não está. É fácil deduzir como resolver o problema: utilizando novamente o modificador public : package br.com.caelum.contas; public class Banco { public String nome; } Podemos testar nosso exemplo anterior, lembrando que utilizar atributos como público não trazencapsulamento e está aqui como ilustração. Voltando ao código do TesteDoBanco , é necessário escrever todo o pacote para identificar qualclasse queremos usar? O exemplo que usamos ficou bem complicado de ler: br.com.caelum.contas.Banco meuBanco = new br.com.caelum.contas.Banco(); Existe uma maneira mais simples de se referenciar a classe Banco : basta importá-la do pacote br.com.caelum.contas : package br.com.caelum.contas.main; // para podermos referenciar // a Banco diretamente import br.com.caelum.contas.Banco; public class TesteDoBanco { public static void main(String[] args) { Banco meuBanco = new Banco(); meuBanco.nome = \"Banco do Brasil\"; } }

. Isso faz com que não precisemos nos referenciar utilizando o fully qualified name, podendo utilizar Banco dentro do nosso código em vez de escrever o longo br.com.caelum.contas.Banco . PACKAGE, IMPORT, CLASS É muito importante manter a ordem! Primeiro, aparece uma (ou nenhuma) vez o package ; depois, pode aparecer um ou mais import s; e, por último, as declarações de classes. IMPORT X.Y.Z.*; É possível \"importar um pacote inteiro\" (todas as classes do pacote, exceto os subpacotes) através do coringa * : import java.util.*; Importar todas as classes de um pacote não implica em perda de performance em tempo de execução, mas pode trazer problemas com classes de mesmo nome! Além disso, importar de um em um é considerado boa prática, pois facilita a leitura para outros programadores. Uma IDE como o Eclipse já vai fazer isso por você, assim como a organização em diretórios.7.4 ACESSO AOS ATRIBUTOS, CONSTRUTORES E MÉTODOS Os modificadores de acesso existentes em Java são quatro, e até o momento já vimos três, mas sóexplicamos dois. public - Todos podem acessar aquilo que for definido como public . Classes, atributos, construtores e métodos podem ser public . protected - Aquilo que é protected pode ser acessado por todas as classes do mesmo pacote e por todas as classes que o estendam, mesmo que essas não estejam no mesmo pacote. Somente atributos, construtores e métodos podem ser protected . padrão (sem nenhum modificador) - Se nenhum modificador for utilizado, todas as classes do mesmo pacote têm acesso ao atributo, construtor, método ou classe. private - A única classe capaz de acessar os atributos, construtores e métodos privados é a própria classe. Classes, como conhecemos, não podem ser private , mas atributos, construtores e métodos sim.

. CLASSES PÚBLICAS Para melhor organizar seu código, o Java não permite mais de uma classe pública por arquivo e o arquivo deve ser NomeDaClasse.java . Uma vez que outros programadores irão utilizar essa classe, quando precisarem olhar o código da mesma, fica mais fácil encontrá-la sabendo que ela está no arquivo de mesmo nome. Classes aninhadas podem ser protected ou private , mas esse é um tópico avançado que não será estudado nesse momento. Editora Casa do Código com livros de uma forma diferente Editoras tradicionais pouco ligam para ebooks e novas tecnologias. Não dominam tecnicamente o assunto para revisar os livros a fundo. Não têm anos de experiência em didáticas com cursos. Conheça a Casa do Código, uma editora diferente, com curadoria da Caelum e obsessão por livros de qualidade a preços justos. Casa do Código, ebook com preço de ebook.7.5 USANDO O ECLIPSE COM PACOTES Você pode usar a perspectiva Java do Eclipse. A view principal de navegação é o Package Explorer,que agrupa classes pelos pacotes em vez de diretórios (você pode usá-la em conjunto com a Navigator,basta também abri-la pelo Window/Show View/Package Explorer).

. Antes de movermos nossas classes, declare-as como públicas e coloque-as em seus respectivosarquivos: um arquivo para cada classe. Você pode mover uma classe de pacote arrastando-a para o destino desejado. Repare que o Eclipse jádeclara package s e import s necessários:

. No Eclipse nunca precisamos declarar um import , pois ele sempre vai sugerir isso quando usarmoso Ctrl+Espaço no nome de uma classe. Você também pode usar o Ctrl+1 no caso da declaração de pacote possuir algum erro.7.6 EXERCÍCIOS: PACOTES Atenção: utilize os recursos do Eclipse para realizar essas mudanças. Use a view package-explorer , que vai auxiliar bastante a manipulação dos arquivos e diretórios. Também utilize os quickfixes quando o Eclipse reclamar dos diversos problemas de compilação que aparecerão. É possível fazeresse exercício inteiro sem modificar uma linha de código manualmente. Aproveite para praticar edescobrir o Eclipse, evite usá-lo apenas como um editor de texto. Por exemplo, com o Eclipse nunca precisamos nos preocupar com os imports: ao usar o autocomplete, ele já joga o import lá em cima. E, se você não fez isso, ele sugere colocar o import .1. Selecionando o src do seu projeto, faça ctrl + N e escreva Package para o seu sistema de Contas começar a utilizar pacotes. Na janela de criação de pacotes escreva o nome completo do pacote seguindo a convenção de código da Sun, desde o br, e o Eclipse tratará de fazer a separação das pastas corretamente. Cuidado: para esse curso, os nomes dos pacotes precisam ser os seguintes: br.com.caelum.contas.main : colocar a classe com o método main aqui (o Teste)

. br.com.caelum.contas.modelo : colocar a classe Conta Antes de corrigir qualquer erro de compilação, primeiro mova todas as suas classes, sem deixar nenhuma no pacote default.2. Se você ainda não tiver separado cada classe em um arquivo, essa é a hora de mudar isso. Coloque cada classe em seu respectivo arquivo .java . Faça isso independente de ela ser pública: é uma boa prática.3. Caso o código não compile prontamente, repare que pelo menos algum método que declaramos é package-private quando, na verdade, precisamos que ele seja public . O mesmo vale para as classes: algumas delas precisarão ser públicas. Se houver algum erro de compilação, use o recurso de quick fix do Eclipse aqui: ele mesmo vai sugerir que o modificador de acesso deve ser público. Para isso, use o ctrl + 1 em cada um dos erros, escolhendo o quick fix mais adequado para seu problema.4. (Opcional) Abra a view Navigator para ver como ficou os arquivos no sistema de arquivos do seu sistema operacional. Para isso, use ctrl + 3, comece a digitar Navigator e escolha a opção de abrir essa view..

.CAPÍTULO 8FERRAMENTAS: JAR E JAVADOC\"Perder tempo em aprender coisas que não interessam, priva-nos de descobrir coisas interessantes\" --Carlos Drummond de Andrade Ao término desse capítulo, você será capaz de: criar o JAR do seu aplicativo; colocar um JAR no build path do seu projeto; ler um javadoc; criar o javadoc do seu aplicativo.8.1 ARQUIVOS, BIBLIOTECAS E VERSÕES Assim que um programa fica pronto, é meio complicado enviar dezenas ou centenas de classes paracada cliente que quer utilizá-lo. O jeito mais simples de trabalhar com um conjunto de classes é compactá-los em um arquivo só. Oformato de compactação padrão é o ZIP com a extensão do arquivo compactado JAR . O ARQUIVO .JAR O arquivo jar ou Java ARchive, possui um conjunto de classes (e arquivos de configurações) compactados, no estilo de um arquivo zip . O arquivo jar pode ser criado com qualquer compactador zip disponível no mercado, inclusive o programa jar que vem junto com o JDK. Para criar um arquivo jar do nosso programa de banco, basta ir ao diretório onde estão contidas asclasses e usar o comando a seguir para criar o arquivo banco.jar com todas as classes dos pacotes br.com.caelum.util e br.com.caelum.banco :jar -cvf banco.jar br/com/caelum/util/*.class br/com/caelum/banco/*.class Para usar esse arquivo banco.jar para rodar o TesteDoBanco basta rodar o java com o arquivo jar como argumento:java -classpath banco.jar br.com.caelum.contas.main.TesteDoBanco

. Para adicionar mais arquivos .jar , que podem ser bibliotecas, ao programa basta rodar o java daseguinte maneira:java -classpath biblioteca1.jar;biblioteca2.jar NomeDaClasse Vale lembrar que o ponto e vírgula utilizado só é válido em ambiente Windows. Em Linux, Mac eoutros Unix, é o dois pontos (varia de acordo com o sistema operacional). Há também um arquivo de manifesto que contém informações do seu jar como, por exemplo, qualclasse ele vai rodar quando o jar for chamado. Mas não se preocupe pois, com o Eclipse, esse arquivo égerado automaticamente. BIBLIOTECAS Diversas bibliotecas podem ser controladas de acordo com a versão por estarem sempre compactadas em um arquivo .jar . Basta verificar o nome da biblioteca (por exemplo log4j- 1.2.13.jar ) para descobrir a versão dela. Então é possível rodar dois programas ao mesmo tempo, cada um utilizando uma versão da biblioteca através do parâmetro -classpath do java. CRIANDO UM .JAR AUTOMATICAMENTE Existem diversas ferramentas que servem para automatizar o processo de deploy, que consiste em compilar, gerar documentação, bibliotecas etc. As duas mais famosas são o ANT e o MAVEN, ambos são projetos do grupo Apache. O Eclipse pode gerar facilmente um jar, porém, se o seu build é complexo e precisa preparar e copiar uma série de recursos, as ferramentas indicadas acima possuem sofisticadas maneiras de rodar um script batch.

. Aprenda se divertindo na Alura Start! Você conhece alguém que tem potencial para tecnologia e programação, mas que nunca escreveu uma linha de código? Pode ser um filho, sobrinho, amigo ou parente distante. Na Alura Start ela vai poder criar games, apps, sites e muito mais! É o começo da jornada com programação e a porta de entrada para uma possível carreira de sucesso. Ela vai estudar em seu próprio ritmo e com a melhor didática. A qualidade da conceituada Alura, agora para Starters. Conheça os cursos online da Alura Start!8.2 GERANDO O JAR PELO ECLIPSE Neste exemplo, vamos gerar o arquivo JAR do nosso projeto a partir do Eclipse: Clique com o botão direito em cima do nome do seu projeto e selecione a opção Export. Na tela Export (como mostra a figura abaixo), selecione a opção \"JAR file\" e aperte o botão

. \"Next\". Na opção \"JAR file:\", selecione o local que você deseja salvar o arquivo JAR. E aperte \"Next\". Na próxima tela, simplesmente clique em next, pois não há nenhuma configuração a ser feita.

. Na tela abaixo, na opção \"select the class of the application entry point\", você deve escolher qual classe será a classe que vai rodar automaticamente quando você executar o JAR. Entre na linha de comando: java -jar banco.jar É comum dar um nome mais significativo aos JARs, incluindo nome da empresa, do projeto eversão, como caelum-banco-1.0.jar .8.3 JAVADOC Como vamos saber o que cada classe tem no Java? Quais são seus métodos, o que eles fazem? E, a partir da Internet, você pode acessar através do link:http://download.java.net/jdk8/docs/api/index.html No site da Oracle, você pode (e deve) baixar a documentação das bibliotecas do Java, frequentementereferida como \"javadoc\" ou API (sendo na verdade a documentação da API).

. Nesta documentação, no quadro superior esquerdo, você encontra os pacotes e, no inferioresquerdo, está a listagem das classes e interfaces do respectivo pacote (ou de todos, caso nenhum tenhasido especificado). Clicando-se em uma classe ou interface, o quadro da direita passa a detalhar todosatributos e métodos. Repare que métodos e atributos privados não estão aí. O importante é documentar o que sua classefaz, e não como ela faz: detalhes de implementação, como atributos e métodos privados, não interessamao desenvolvedor que usará a sua biblioteca (ou, ao menos, não deveriam interessar). Você também consegue gerar esse javadoc a partir da linha de comando, com o comando: javadoc .8.4 GERANDO O JAVADOC Para gerar o Javadoc a partir do Eclipse é muito simples, siga os passos abaixo: Na barra de menu, selecione o menu Project, depois a opção \"Generate Javadoc...\". (apenas disponível se estiver na perspectiva Java, mas você pode acessar o mesmo wizard pelo export do projeto).

. Em seguida, aparecerão as opções para gerar a documentação do seu sistema, selecione todas as classes do seu sistema e deixe as outras opções como estão. Não esqueça de marcar o caminho da opção \"Destination\", pois é lá que estará sua documentação.

. Abra a documentação através do caminho que você marcou e abra o arquivo index.html, que vai chamar uma página semelhante a essa da figura abaixo. Para colocarmos comentários na documentação, devemos adicionar ao código, sob forma decomentário, abrindo o texto com /** e fechando com */ e, nas outras linhas, apenas colocando * .Também podemos definir outras informações neste texto, como: autor, versão, parâmetros, retorno, etc.Adicione alguns comentários ao seu projeto como abaixo: /** * Classe responsável por moldar as Contas do Banco * * @author Manoel Santos da Silva */ public class Conta{ ... } Ou adicione alguns comentários em algum método seu: /** * Metodo que incrementa o saldo. * @param valor */ public void deposita(double valor) { ...

. } Veja como ficou: Seus livros de tecnologia parecem do século passado? Conheça a Casa do Código, uma nova editora, com autores de destaque no mercado, foco em ebooks (PDF, epub, mobi), preços imbatíveis e assuntos atuais. Com a curadoria da Caelum e excelentes autores, é uma abordagem diferente para livros de tecnologia no Brasil. Casa do Código, Livros de Tecnologia.8.5 EXERCÍCIOS: JAR E JAVADOC

.1. Gere um jar do seu sistema com o arquivo de manifesto. Execute-o com java -jar : java -jar caelum-banco-1.0.jar Se o Windows ou o Linux foi configurado para trabalhar com a extensão .jar, basta você dar um duplo clique no arquivo, que ele será \"executado\": o arquivo Manifest será lido para que ele descubra qual é a classe com main que o Java deve processar.2. Gere o Javadoc do seu sistema. Para isso, vá ao menu Project, depois à opção Generate Javadoc, se estiver na perspectiva Java. Se não, dê um clique com o botão direito no seu projeto, escolha Export e depois javadoc e siga o procedimento descrito na última seção deste capítulo. Independente da perspectiva que você usa no Eclipse, você também pode usar o ctrl + 3 e começar a escrever JavaDoc , até que a opção de exportar o JavaDoc apareça. INTERFACE VERSUS IMPLEMENTAÇÃO NOVAMENTE! Repare que a documentação gerada não mostra o conteúdo dos métodos, nem atributos e métodos privados! Isso faz parte da implementação, e o que importa para quem usa uma biblioteca é a interface: o que ela faz.8.6 IMPORTANDO UM JAR EXTERNO Já sabemos como documentar nosso projeto e gerar um jar para distribuí-lo mas ela ainda não temuma interface gráfica do usuário. Se quisermos rodar o nosso sistema temos que executá-lo pelo terminalcom os valores hard-coded. Seria mais interessante que tivéssemos uma interface mais amigável para queo usuário pudesse interagir com o nosso sistema. Ao mesmo tempo, não queremos nos preocupar nessemomento em criar todas as classes para representar essa interface gráfica, queremos apenas utilizar algojá pronto. Para isso, vamos importar uma biblioteca externa. O próprio Eclipse já nos dá suporte para aimportação de jars. Para fazer isso, basta ir no menu Project -> Properties, selecionar a opção Java BuildPath, depois selecionar a aba Libraries e, finalmente, clicar no botão Add External Jars... . Agora é sóselecionar o jar a ser importado e clicar em Open. Clique em Ok novamente para fechar a janela deimportação e pronto! Nossa biblioteca já está pronta para ser utilizada.8.7 EXERCÍCIOS: IMPORTANDO UM JAR1. Vamos importar um jar que contém a interface gráfica do usuário para o nosso sistema de contas. Vá no menu Project -> Properties

. Selecione a opção Java Build Path Selecione a aba Libraries Clique no botão Add External Jars... Selecione o arquivo fj11-lib-contas.jar localizado na pasta dos arquivos dos cursos/11 Clique no botão Ok para fechar a janela de importação2. Para verificarmos que a importação deu certo, vamos chamar uma classe da biblioteca importada para exibir uma janela de boas-vindas. Crie uma classe TestaJar no pacote br.com.caelum.contas.main . Crie também o método main .3. Dentro do método criado, vamos invocar o método main da classe OlaMundo que existe no jar importado. Seu código deve ficar dessa maneira: package br.com.caelum.contas.main; import br.com.caelum.javafx.api.main.OlaMundo; public class TestaJar { public static void main(String[] args) { OlaMundo.main(args); } } Não esqueça de importar a classe OlaMundo do pacote br.com.caelum.javafx.api.main . Use o atalho ctrl + shift + O.4. Execute a sua aplicação e veja se apareceu uma janela de boas-vindas como a seguir:

. Agora é a melhor hora de respirar mais tecnologia! Se você está gostando dessa apostila, certamente vai aproveitar os cursos online que lançamos na plataforma Alura. Você estuda a qualquer momento com a qualidade Caelum. Programação, Mobile, Design, Infra, Front-End e Business! Ex-aluno da Caelum tem 15% de desconto, siga o link! Conheça a Alura Cursos Online.8.8 MANIPULANDO A CONTA PELA INTERFACE GRÁFICA Agora que já importamos o Jar que contém a interface gráfica, vamos dar uma olhada na primeiratela do nosso sistema:

. Nesta tela, podemos perceber que temos botões para as ações de criação de conta, saque e depósito,que devem utilizar a implementação existente em nossa classe Conta . Se quisermos visualizar a tela, podemos criar um main que chamará a classe TelaDeContas responsável pela sua exibição:package br.com.caelum.contas.main;import br.com.caelum.javafx.api.main.TelaDeContas;public class TestaContas { public static void main(String[] args) { TelaDeContas.main(args); }}

. Ao executarmos a aplicação ocorrerá um erro: Mas por que este erro ocorreu? Acontece que a tela precisa conhecer alguém que saiba executar asações de saque e depósito na conta, que consiga buscar os dados da tela para popular a conta. Como nãotemos ninguém que saiba fazer isto ainda, ocorreu o erro. Vamos então criar a classe ManipuladorDeContas que será responsável por fazer esta \"ponte\" entrea tela e a classe de Conta :package br.com.caelum.contas;public class ManipuladorDeContas {} Agora, ao executarmos a aplicação, veremos que a tela aparece com sucesso:

. E se tentarmos clicar no botão de criação de conta? Também ocorre um erro!

. Desta vez o erro indica que falta o método criaConta dentro da classe ManipuladorDeContas .Vamos então criá-lo:public class ManipuladorDeContas { public void criaConta(){ Conta conta = new Conta(); conta.setAgencia(\"1234\"); conta.setNumero(56789); conta.setTitular(\"Batman\"); }} Para conseguirmos obter as informações da tela, todos os métodos que criaremos precisam receberum parâmetro do tipo Evento que conterá as informações digitadas. Mesmo que não utilizemos esteparâmetro, precisamos recebê-lo.import br.com.caelum.javafx.api.util.Evento;public class ManipuladorDeContas { public void criaConta(Evento evento){ Conta conta = new Conta(); conta.setAgencia(\"1234\"); conta.setNumero(56789); conta.setTitular(\"Batman\"); }} Se tentarmos executar a aplicação e clicar no botão cria conta, vemos que agora não ocorre maisnenhum erro mas ao mesmo tempo os dados da conta não são populados na tela. Isto acontece pois avariável conta é apenas local, ou seja, ela só existe dentro do método criaConta . Além disso sequiséssemos depositar um valor na conta, em qual conta depositaríamos? Ela não é visível para nenhum

.outro método! Precisamos que esta variável seja um atributo do ManipuladorDeContas . Vamos alterar:import br.com.caelum.javafx.api.util.Evento;public class ManipuladorDeContas { private Conta conta; public void criaConta(Evento evento){ this.conta = new Conta(); this.conta.setAgencia(\"1234\"); this.conta.setNumero(56789); this.conta.setTitular(\"Batman\"); }} Testando agora conseguimos ver os dados da conta na tela!

. Só falta criarmos os métodos saca e deposita . Vamos começar implementando o método deposita . Nele precisamos do valor digitado pelo usuário na tela e é pra isto que serve a classe Evento . Se quisermos buscar um valor do tipo double , podemos invocar o método double passando o nome do campo que queremos recuperar como parâmetro. Com o valor em mãos, podemosentão passá-lo para o método desejado. Nosso método fica:import br.com.caelum.javafx.api.util.Evento;public class ManipuladorDeContas { // ... public void deposita(Evento evento){ double valorDigitado = evento.getDouble(\"valor\"); this.conta.deposita(valorDigitado); }} Podemos fazer o mesmo para o método saca :import br.com.caelum.javafx.api.util.Evento;public class ManipuladorDeContas { // ... public void deposita(Evento evento){ double valorDigitado = evento.getDouble(\"valor\"); this.conta.deposita(valorDigitado); } public void saca(Evento evento){ double valorDigitado = evento.getDouble(\"valor\"); this.conta.saca(valorDigitado); }} Agora conseguimos rodar a aplicação e chamar as ações de saque e depósito que o saldo é atualizadocom sucesso!

.8.9 EXERCÍCIOS: MOSTRANDO OS DADOS DA CONTA NA TELA1. Crie a classe ManipuladorDeContas dentro do pacote br.com.caelum.contas . Repare que os pacotes br.com.caelum.contas.main e br.com.caelum.contas.modelo são subpacotes do pacote br.com.caelum.contas , portanto o pacote br.com.caelum.contas já existe. Para criar a classe neste pacote, basta selecioná-lo na janela de criação da classe:

. A classe ManipuladorDeContas fará a ligação da Conta com a tela, por isso precisaremos declarar um atributo do tipo Conta .2. Crie o método criaConta que recebe como parâmetro um objeto do tipo Evento . Instancie uma conta para o atributo conta e coloque os valores de numero , agencia e titular . Algo como: public void criaConta(Evento evento){ this.conta = new Conta(); this.conta.setTitular(\"Batman\"); // faça o mesmo para os outros atributos }3. Com a conta instanciada, agora podemos implementar as funcionalidades de saque e depósito. Crie o método deposita que recebe um Evento , que é a classe que retorna os dados da tela nos tipos que precisamos. Por exemplo, se quisermos o valor a depositar sabemos que ele é do tipo double e que o nome do campo na tela é valor então podemos fazer: public void deposita(Evento evento){ double valorDigitado = evento.getDouble(\"valor\"); this.conta.deposita(valorDigitado); }4. Crie agora o método saca . Ele também deve receber um Evento nos mesmos moldes do

. deposita .5. Precisamos agora testar nossa aplicação, crie a classe TestaContas dentro do pacote br.com.caelum.contas com um main . Nela vamos chamar o main da classe TelaDeContas que mostrará a tela de nosso sistema. Não se esqueça de fazer o import desta classe! import br.com.caelum.javafx.api.main.TelaDeContas; public class TestaContas { public static void main(String[] args) { TelaDeContas.main(args); } } Rode a aplicação, crie a conta e tente fazer as operações de saque e depósito. Tudo deve funcionar normalmente.

.CAPÍTULO 9HERANÇA, REESCRITA E POLIMORFISMO\"O homem absurdo é aquele que nunca muda.\" -- Georges Clemenceau Ao término desse capítulo, você será capaz de: dizer o que é herança e quando utilizá-la; reutilizar código escrito anteriormente; criar classes filhas e reescrever métodos; usar todo o poder que o polimorfismo dá.9.1 REPETINDO CÓDIGO? Como toda empresa, nosso Banco possui funcionários. Vamos modelar a classe Funcionario : public class Funcionario { private String nome; private String cpf; private double salario; // métodos devem vir aqui } Além de um funcionário comum, há também outros cargos, como os gerentes. Os gerentes guardama mesma informação que um funcionário comum, mas possuem outras informações, além de terfuncionalidades um pouco diferentes. Um gerente no nosso banco possui também uma senha numéricaque permite o acesso ao sistema interno do banco, além do número de funcionários que ele gerencia:public class Gerente { private String nome; private String cpf; private double salario; private int senha; private int numeroDeFuncionariosGerenciados; public boolean autentica(int senha) { if (this.senha == senha) { System.out.println(\"Acesso Permitido!\"); return true; } else { System.out.println(\"Acesso Negado!\"); return false; } } // outros métodos

.} PRECISAMOS MESMO DE OUTRA CLASSE? Poderíamos ter deixado a classe Funcionario mais genérica, mantendo nela senha de acesso, e o número de funcionários gerenciados. Caso o funcionário não fosse um gerente, deixaríamos estes atributos vazios. Essa é uma possibilidade, porém podemos começar a ter muito atributos opcionais, e a classe ficaria estranha. E em relação aos métodos? A classe Gerente tem o método autentica , que não faz sentido existir em um funcionário que não é gerente. Se tivéssemos um outro tipo de funcionário que tem características diferentes do funcionáriocomum, precisaríamos criar uma outra classe e copiar o código novamente! Além disso, se um dia precisarmos adicionar uma nova informação para todos os funcionários,precisaremos passar por todas as classes de funcionário e adicionar esse atributo. O problema acontecenovamente por não centralizarmos as informações principais do funcionário em um único lugar! Existe um jeito, em Java, de relacionarmos uma classe de tal maneira que uma delas herda tudo que aoutra tem. Isto é uma relação de classe mãe e classe filha. No nosso caso, gostaríamos de fazer com que o Gerente tivesse tudo que um Funcionario tem, gostaríamos que ela fosse uma extensão de Funcionario . Fazemos isto através da palavra chave extends . public class Gerente extends Funcionario { private int senha; private int numeroDeFuncionariosGerenciados; public boolean autentica(int senha) { if (this.senha == senha) { System.out.println(\"Acesso Permitido!\"); return true; } else { System.out.println(\"Acesso Negado!\"); return false; } } // setter da senha omitido } Em todo momento que criarmos um objeto do tipo Gerente , este objeto possuirá também osatributos definidos na classe Funcionario , pois um Gerente é um Funcionario :

. public class TestaGerente { public static void main(String[] args) { Gerente gerente = new Gerente(); // podemos chamar métodos do Funcionario: gerente.setNome(\"João da Silva\"); // e também métodos do Gerente! gerente.setSenha(4231); } } Dizemos que a classe Gerente herda todos os atributos e métodos da classe mãe, no nosso caso, a Funcionario . Para ser mais preciso, ela também herda os atributos e métodos privados, porém nãoconsegue acessá-los diretamente. Para acessar um membro privado na filha indiretamente, serianecessário que a mãe expusesse um outro método visível que invocasse esse atributo ou método privado. SUPER E SUB CLASSE A nomenclatura mais encontrada é que Funcionario é a superclasse de Gerente , e Gerente é a subclasse de Funcionario . Dizemos também que todo Gerente é um Funcionário . Outra forma é dizer que Funcionario é classe mãe de Gerente e Gerente é classe filha de Funcionario . E se precisamos acessar os atributos que herdamos? Não gostaríamos de deixar os atributos de Funcionario , public , pois dessa maneira qualquer um poderia alterar os atributos dos objetos destetipo. Existe um outro modificador de acesso, o protected , que fica entre o private e o public . Umatributo protected só pode ser acessado (visível) pela própria classe, por suas subclasses, e pelasclasses que se encontram no mesmo pacote. public class Funcionario { protected String nome; protected String cpf; protected double salario; // métodos devem vir aqui }

. SEMPRE USAR PROTECTED? Então por que usar private ? Depois de um tempo programando orientado a objetos, você vai começar a sentir que nem sempre é uma boa ideia deixar que a classe filha acesse os atributos da classe mãe, pois isso quebra um pouco a ideia de que só aquela classe deveria manipular seus atributos. Essa é uma discussão um pouco mais avançada. Além disso, não só as subclasses, mas também as outras classes que se encontram no mesmo pacote, podem acessar os atributos protected . Veja outras alternativas ao protected no exercício de discussão em sala de aula juntamente com o instrutor. Da mesma maneira, podemos ter uma classe Diretor que estenda Gerente e a classe Presidente pode estender diretamente de Funcionario . Fique claro que essa é uma decisão de negócio. Se Diretor vai estender de Gerente ou não, vaidepender se, para você, Diretor é um Gerente. Uma classe pode ter várias filhas, mas pode ter apenas uma mãe, é a chamada herança simples dojava.

. Editora Casa do Código com livros de uma forma diferente Editoras tradicionais pouco ligam para ebooks e novas tecnologias. Não dominam tecnicamente o assunto para revisar os livros a fundo. Não têm anos de experiência em didáticas com cursos. Conheça a Casa do Código, uma editora diferente, com curadoria da Caelum e obsessão por livros de qualidade a preços justos. Casa do Código, ebook com preço de ebook.9.2 REESCRITA DE MÉTODO Todo fim de ano, os funcionários do nosso banco recebem uma bonificação. Os funcionárioscomuns recebem 10% do valor do salário e os gerentes, 15%. Vamos ver como fica a classe Funcionario : public class Funcionario { protected String nome; protected String cpf; protected double salario; public double getBonificacao() { return this.salario * 0.10; } // métodos } Se deixarmos a classe Gerente como ela está, ela vai herdar o método getBonificacao . Gerente gerente = new Gerente(); gerente.setSalario(5000.0); System.out.println(gerente.getBonificacao()); O resultado aqui será 500. Não queremos essa resposta, pois o gerente deveria ter 750 de bônus nessecaso. Para consertar isso, uma das opções seria criar um novo método na classe Gerente , chamado, porexemplo, getBonificacaoDoGerente . O problema é que teríamos dois métodos em Gerente ,confundindo bastante quem for usar essa classe, além de que cada um da uma resposta diferente. No Java, quando herdamos um método, podemos alterar seu comportamento. Podemos reescrever(reescrever, sobrescrever, override) este método: public class Gerente extends Funcionario { int senha; int numeroDeFuncionariosGerenciados;

. public double getBonificacao() { return this.salario * 0.15; } // ... } Agora o método está correto para o Gerente . Refaça o teste e veja que o valor impresso é o correto(750): Gerente gerente = new Gerente(); gerente.setSalario(5000.0); System.out.println(gerente.getBonificacao()); A ANOTAÇÃO @OVERRIDE Há como deixar explícito no seu código que determinador método é a reescrita de um método da sua classe mãe. Fazemos isso colocando @Override em cima do método. Isso é chamado anotação. Existem diversas anotações e cada uma vai ter um efeito diferente sobre seu código. @Override public double getBonificacao() { return this.salario * 0.15; } Repare que, por questões de compatibilidade, isso não é obrigatório. Mas caso um método esteja anotado com @Override, ele necessariamente precisa estar reescrevendo um método da classe mãe.9.3 INVOCANDO O MÉTODO REESCRITO Depois de reescrito, não podemos mais chamar o método antigo que fora herdado da classe mãe:realmente alteramos o seu comportamento. Mas podemos invocá-lo no caso de estarmos dentro daclasse. Imagine que para calcular a bonificação de um Gerente devemos fazer igual ao cálculo de um Funcionario porém adicionando R$ 1000. Poderíamos fazer assim: public class Gerente extends Funcionario { int senha; int numeroDeFuncionariosGerenciados; public double getBonificacao() { return this.salario * 0.10 + 1000; } // ... } Aqui teríamos um problema: o dia que o getBonificacao do Funcionario mudar, precisaremos

.mudar o método do Gerente para acompanhar a nova bonificação. Para evitar isso, o getBonificacao do Gerente pode chamar o do Funcionario utilizando a palavra chave super . public class Gerente extends Funcionario { int senha; int numeroDeFuncionariosGerenciados; public double getBonificacao() { return super.getBonificacao() + 1000; } // ... } Essa invocação vai procurar o método com o nome getBonificacao de uma super classe de Gerente . No caso ele logo vai encontrar esse método em Funcionario . Essa é uma prática comum, pois muitos casos o método reescrito geralmente faz \"algo a mais\" que ométodo da classe mãe. Chamar ou não o método de cima é uma decisão sua e depende do seu problema.Algumas vezes não faz sentido invocar o método que reescrevemos.9.4 POLIMORFISMO O que guarda uma variável do tipo Funcionario ? Uma referência para um Funcionario , nunca oobjeto em si. Na herança, vimos que todo Gerente é um Funcionario , pois é uma extensão deste. Podemosnos referir a um Gerente como sendo um Funcionario . Se alguém precisa falar com um Funcionario do banco, pode falar com um Gerente ! Porque? Pois Gerente é um Funcionario .Essa é a semântica da herança. Gerente gerente = new Gerente(); Funcionario funcionario = gerente; funcionario.setSalario(5000.0); Polimorfismo é a capacidade de um objeto poder ser referenciado de várias formas. (cuidado,polimorfismo não quer dizer que o objeto fica se transformando, muito pelo contrário, um objeto nascede um tipo e morre daquele tipo, o que pode mudar é a maneira como nos referimos a ele). Até aqui tudo bem, mas e se eu tentar:

.funcionario.getBonificacao(); Qual é o retorno desse método? 500 ou 750? No Java, a invocação de método sempre vai ser decididaem tempo de execução. O Java vai procurar o objeto na memória e, aí sim, decidir qual método deve serchamado, sempre relacionando com sua classe de verdade, e não com a que estamos usando parareferenciá-lo. Apesar de estarmos nos referenciando a esse Gerente como sendo um Funcionario , ométodo executado é o do Gerente . O retorno é 750. Parece estranho criar um gerente e referenciá-lo como apenas um funcionário. Por que faríamosisso? Na verdade, a situação que costuma aparecer é a que temos um método que recebe um argumentodo tipo Funcionario : class ControleDeBonificacoes { private double totalDeBonificacoes = 0; public void registra(Funcionario funcionario) { this.totalDeBonificacoes += funcionario.getBonificacao(); } public double getTotalDeBonificacoes() { return this.totalDeBonificacoes; } } E, em algum lugar da minha aplicação (ou no main , se for apenas para testes): ControleDeBonificacoes controle = new ControleDeBonificacoes(); Gerente funcionario1 = new Gerente(); funcionario1.setSalario(5000.0); controle.registra(funcionario1); Funcionario funcionario2 = new Funcionario(); funcionario2.setSalario(1000.0); controle.registra(funcionario2); System.out.println(controle.getTotalDeBonificacoes()); Repare que conseguimos passar um Gerente para um método que recebe um Funcionario comoargumento. Pense como numa porta na agência bancária com o seguinte aviso: \"Permitida a entradaapenas de Funcionários\". Um gerente pode passar nessa porta? Sim, pois Gerente é um Funcionario . Qual será o valor resultante? Não importa que dentro do método registra do ControleDeBonificacoes receba Funcionario . Quando ele receber um objeto que realmente é um Gerente , o seu método reescrito será invocado. Reafirmando: não importa como nos referenciamos aum objeto, o método que será invocado é sempre o que é dele. No dia em que criarmos uma classe Secretaria , por exemplo, que é filha de Funcionario ,precisaremos mudar a classe de ControleDeBonificacoes ? Não. Basta a classe Secretaria reescrever os métodos que lhe parecerem necessários. É exatamente esse o poder do polimorfismo,

.juntamente com a reescrita de método: diminuir o acoplamento entre as classes, para evitar que novoscódigos resultem em modificações em inúmeros lugares. Repare que quem criou ControleDeBonificacoes pode nunca ter imaginado a criação da classe Secretaria ou Engenheiro . Contudo, não será necessário reimplementar esse controle em cadanova classe: reaproveitamos aquele código. HERANÇA VERSUS ACOPLAMENTO Note que o uso de herança aumenta o acoplamento entre as classes, isto é, o quanto uma classe depende de outra. A relação entre classe mãe e filha é muito forte e isso acaba fazendo com que o programador das classes filhas tenha que conhecer a implementação da classe mãe e vice-versa - fica difícil fazer uma mudança pontual no sistema. Por exemplo, imagine se tivermos que mudar algo na nossa classe Funcionario , mas não quiséssemos que todos os funcionários sofressem a mesma mudança. Precisaríamos passar por cada uma das filhas de Funcionario verificando se ela se comporta como deveria ou se devemos sobrescrever o tal método modificado. Esse é um problema da herança, e não do polimorfismo, que resolveremos mais tarde com a ajuda de Interfaces. Já conhece os cursos online Alura? A Alura oferece centenas de cursos online em sua plataforma exclusiva de ensino que favorece o aprendizado com a qualidade reconhecida da Caelum. Você pode escolher um curso nas áreas de Programação, Front-end, Mobile, Design & UX, Infra e Business, com um plano que dá acesso a todos os cursos. Ex aluno da Caelum tem 15% de desconto neste link! Conheça os cursos online Alura.9.5 UM OUTRO EXEMPLO Imagine que vamos modelar um sistema para a faculdade que controle as despesas com funcionáriose professores. Nosso funcionário fica assim:

. public class EmpregadoDaFaculdade { private String nome; private double salario; public double getGastos() { return this.salario; } public String getInfo() { return \"nome: \" + this.nome + \" com salário \" + this.salario; } // métodos de get, set e outros } O gasto que temos com o professor não é apenas seu salário. Temos de somar um bônus de 10 reaispor hora/aula. O que fazemos então? Reescrevemos o método. Assim como o getGastos é diferente, o getInfo também será, pois temos de mostrar as horas/aula também. public class ProfessorDaFaculdade extends EmpregadoDaFaculdade { private int horasDeAula; public double getGastos() { return this.getSalario() + this.horasDeAula * 10; } public String getInfo() { String informacaoBasica = super.getInfo(); String informacao = informacaoBasica + \" horas de aula: \" + this.horasDeAula; return informacao; } // métodos de get, set e outros que forem necessários } A novidade, aqui, é a palavra chave super . Apesar do método ter sido reescrito, gostaríamos deacessar o método da classe mãe, para não ter de copiar e colocar o conteúdo desse método e depoisconcatenar com a informação das horas de aula. Como tiramos proveito do polimorfismo? Imagine que temos uma classe de relatório: public class GeradorDeRelatorio { public void adiciona(EmpregadoDaFaculdade f) { System.out.println(f.getInfo()); System.out.println(f.getGastos()); } } Podemos passar para nossa classe qualquer EmpregadoDaFaculdade ! Vai funcionar tanto paraprofessor, quanto para funcionário comum. Um certo dia, muito depois de terminar essa classe de relatório, resolvemos aumentar nosso sistema,e colocar uma classe nova, que representa o Reitor . Como ele também é um EmpregadoDaFaculdade , será que vamos precisar alterar algo na nossa classe de Relatorio ? Não.Essa é a ideia! Quem programou a classe GeradorDeRelatorio nunca imaginou que existiria umaclasse Reitor e, mesmo assim, o sistema funciona. public class Reitor extends EmpregadoDaFaculdade { // informações extras public String getInfo() {

. return super.getInfo() + \" e ele é um reitor\"; } // não sobrescrevemos o getGastos!!! }9.6 UM POUCO MAIS... Se não houvesse herança em Java, como você poderia reaproveitar o código de outra classe? Uma discussão muito atual é sobre o abuso no uso da herança. Algumas pessoas usam herança apenas para reaproveitar o código, quando poderiam ter feito uma composição. Procure sobre herança versus composição. Mesmo depois de reescrever um método da classe mãe, a classe filha ainda pode acessar o método antigo. Isto é feito através da palavra chave super.método() . Algo parecido ocorre entre os construtores das classes, o que? MAIS SOBRE O MAU USO DA HERANÇA No blog da Caelum existe um artigo interessante abordando esse tópico: http://blog.caelum.com.br/2006/10/14/como-nao-aprender-orientacao-a-objetos-heranca/ James Gosling, um dos criadores do Java, é um crítico do mau uso da herança. Nesta entrevista ele discute a possibilidade de se utilizar apenas interfaces e composição, eliminando a necessidade da herança: http://www.artima.com/intv/gosling3P.html9.7 EXERCÍCIOS: HERANÇA E POLIMORFISMO1. Vamos ter mais de um tipo de conta no nosso sistema então vamos precisar de uma nova tela para cadastrar os diferentes tipos de conta. Essa tela já está pronta e para utilizá-la só precisamos alterar a classe que estamos chamando no método main() no TestaContas.java : package br.com.caelum.contas.main; import br.com.caelum.javafx.api.main.SistemaBancario; public class TestaContas { public static void main(String[] args) { SistemaBancario.mostraTela(false); // TelaDeContas.main(args); } }

.2. Ao rodar a classe TestaContas agora, teremos a tela abaixo: Vamos entrar na tela de criação de contas para vermos o que precisamos implementar para que o sistema funcione. Para isso, clique no botão Nova Conta. A seguinte tela aparecerá: Podemos perceber que além das informações que já tínhamos na conta, temos agora o tipo: se queremos uma conta corrente ou uma conta poupança. Vamos então criar as classes correspondentes. Crie a classe ContaCorrente no pacote br.com.caelum.contas.modelo e faça com que ela seja filha da classe Conta Crie a classe ContaPoupanca no pacote br.com.caelum.contas.modelo e faça com que ela seja filha da classe Conta 3. Precisamos pegar os dados da tela para conseguirmos criar a conta correspondente. No ManipuladorDeContas vamos alterar o método criaConta . Atualmente, apenas criamos uma nova conta com os dados direto no código. Vamos fazer com que agora os dados sejam recuperados

. da tela para colocarmos na nova conta, faremos isso utilizando o objeto evento : public void criaConta(Evento evento) { this.conta = new Conta(); this.conta.setAgencia(evento.getString(\"agencia\")); this.conta.setNumero(evento.getInt(\"numero\")); this.conta.setTitular(evento.getString(\"titular\")); } Mas precisamos dizer qual tipo de conta que queremos criar! Devemos então recuperar o tipo da conta escolhido e criar a conta correspondente. Para isso, ao invés de criar um objeto do tipo 'Conta', vamos usar o método getSelecionadoNoRadio do objeto evento para pegar o tipo, fazer um if para verificar esse tipo e só depois criar o objeto do tipo correspondente. Após essas mudanças, o método criaConta ficará como abaixo: public void criaConta(Evento evento) { String tipo = evento.getSelecionadoNoRadio(\"tipo\"); if (tipo.equals(\"Conta Corrente\")) { this.conta = new ContaCorrente(); } else if (tipo.equals(\"Conta Poupança\")) { this.conta = new ContaPoupanca(); } this.conta.setAgencia(evento.getString(\"agencia\")); this.conta.setNumero(evento.getInt(\"numero\")); this.conta.setTitular(evento.getString(\"titular\")); }4. Apesar de já conseguirmos criar os dois tipos de contas, nossa lista não consegue exibir o tipo de cada conta na lista da tela inicial. Para resolver isso, podemos criar um método getTipo em cada uma de nossas contas fazendo com que a conta corrente devolva a string \"Conta Corrente\" e a conta poupança devolva a string \"Conta Poupança\": public class ContaCorrente extends Conta { public String getTipo() { return \"Conta Corrente\"; } } public class ContaPoupanca extends Conta { public String getTipo() { return \"Conta Poupança\"; } }5. Altere os métodos saca e deposita para buscarem o campo valorOperacao ao invés de apenas valor na classe ManipuladorDeContas .6. Vamos mudar o comportamento da operação de saque de acordo com o tipo de conta que estiver sendo utilizada. Na classe ManipuladorDeContas vamos alterar o método saca para tirar 10 centavos de cada saque em uma conta corrente: public void saca(Evento evento) { double valor = evento.getDouble(\"valorOperacao\"); if (this.conta.getTipo().equals(\"Conta Corrente\")){ this.conta.saca(valor + 0.10);

. } else { this.conta.saca(valor); } } Ao tentarmos chamar o método getTipo , o Eclipse reclamou que esse método não existe na classe Conta apesar de existir nas classes filhas. Como estamos tratando todas as contas genericamente, só conseguimos acessar os métodos da classe mãe. Vamos então colocá-lo na classe Conta : public class Conta { public String getTipo() { return \"Conta\"; } }7. Agora o código compila mas temos um outro problema. A lógica do nosso saque vazou para a classe ManipuladorDeContas . Se algum dia precisarmos alterar o valor da taxa no saque, teríamos que mudar em todos os lugares onde fazemos uso do método saca . Esta lógica deveria estar encapsulada dentro do método saca de cada conta. Vamos então sobrescrever o método dentro da classe ContaCorrente : public class ContaCorrente extends Conta { @Override public void saca(double valor) { this.saldo -= (valor + 0.10); } // restante da classe } Repare que, para acessar o atributo saldo herdado da classe Conta , você vai precisar mudar o modificador de visibilidade de saldo para protected . Agora que a lógica está encapsulada, podemos corrigir o método saca da classe ManipuladorDeContas : public void saca(Evento evento) { double valor = evento.getDouble(\"valorOperacao\"); this.conta.saca(valor); } Perceba que agora tratamos a conta de forma genérica!8. Rode a classe TestaContas , adicione uma conta de cada tipo e veja se o tipo é apresentado corretamente na lista de contas da tela inicial. Agora, clique na conta corrente apresentada na lista para abrir a tela de detalhes de contas. Teste as operações de saque e depósito e perceba que a conta apresenta o comportamento de uma conta corrente conforme o esperado. E se tentarmos realizar uma transferência da conta corrente para a conta poupança? O que acontece?

. 9. Vamos começar implementando o método transfere na classe Conta : public void transfere(double valor, Conta conta) { this.saca(valor); conta.deposita(valor); } Também precisamos implementar o método transfere na classe ManipuladorDeContas para fazer o vínculo entre a tela e a classe Conta : public void transfere(Evento evento) { Conta destino = (Conta) evento.getSelecionadoNoCombo(\"destino\"); conta.transfere(evento.getDouble(\"valorTransferencia\"), destino); } Rode de novo a aplicação e teste a operação de transferência.10. Considere o código abaixo: Conta c = new Conta(); ContaCorrente cc = new ContaCorrente(); ContaPoupanca cp = new ContaPoupanca(); Se mudarmos esse código para: Conta c = new Conta(); Conta cc = new ContaCorrente(); Conta cp = new ContaPoupanca(); Compila? Roda? O que muda? Qual é a utilidade disso? Realmente, essa não é a maneira mais útil do polimorfismo. Porém existe uma utilidade de declararmos uma variável de um tipo menos específico do que o objeto realmente é, como fazemos na classe ManipuladorDeContas . É extremamente importante perceber que não importa como nos referimos a um objeto, o método que será invocado é sempre o mesmo! A JVM vai descobrir em tempo de execução qual deve ser invocado, dependendo de que tipo é aquele objeto, não importando como nos referimos a ele.11. (Opcional) A nossa classe Conta devolve a palavra \"Conta\" no método getTipo . Use a palavra chave super nos métodos getTipo reescritos nas classes filhas, para não ter de reescreve a palavra \"Conta\" ao devolver os tipos \"Conta Corrente\" e \"Conta Poupança\".12. (Opcional) Se você precisasse criar uma classe ContaInvestimento , e seu método saca fosse complicadíssimo, você precisaria alterar a classe ManipuladorDeContas ?

. Saber inglês é muito importante em TI Na Alura Língua você reforça e aprimora seu inglês! Usando a técnica Spaced Repetitions o aprendizado naturalmente se adapta ao seu conhecimento. Exercícios e vídeos interativos fazem com que você pratique em situações cotidianas. Além disso, todas as aulas possuem explicações gramaticais, para você entender completamente o que está aprendendo. Aprender inglês é fundamental para o profissional de tecnologia de sucesso! Pratique seu inglês na Alura Língua.9.8 DISCUSSÕES EM AULA: ALTERNATIVAS AO ATRIBUTOPROTECTED Discuta com o instrutor e seus colegas alternativas ao uso do atributo protected na herança.Preciso realmente afrouxar o encapsulamento do atributo por causa da herança? Como fazer para oatributo continuar private na mãe e as filhas conseguirem de alguma formar trabalhar com ele?

.CAPÍTULO 10CLASSES ABSTRATAS\"Dá-se importância aos antepassados quando já não temos nenhum.\" -- François Chateaubriand Ao término desse capítulo, você será capaz de utilizar classes abstratas, quando necessário.10.1 REPETINDO MAIS CÓDIGO? Neste capítulo, aconselhamos que você passe a usar o Eclipse. Você já tem conhecimento suficientedos erros de compilação do javac e agora pode aprender as facilidades que o Eclipse te traz ao ajudarvocê no código com os chamados quick fixes e quick assists. Vamos recordar em como pode estar nossa classe Funcionario : public class Funcionario { protected String nome; protected String cpf; protected double salario; public double getBonificacao() { return this.salario * 1.2; } // outros métodos aqui } Considere o nosso ControleDeBonificacao : public class ControleDeBonificacoes { private double totalDeBonificacoes = 0; public void registra(Funcionario f) { System.out.println(\"Adicionando bonificação do funcionario: \" + f); this.totalDeBonificacoes += f.getBonificacao(); } public double getTotalDeBonificacoes() { return this.totalDeBonificacoes; } } Nosso método registra recebe qualquer referência do tipo Funcionario , isto é, podem serobjetos do tipo Funcionario e qualquer de seus subtipos: Gerente , Diretor e, eventualmente,

.alguma nova subclasse que venha ser escrita, sem prévio conhecimento do autor da ControleDeBonificacao . Estamos utilizando aqui a classe Funcionario para o polimorfismo. Se não fosse ela, teríamos umgrande prejuízo: precisaríamos criar um método registra para receber cada um dos tipos de Funcionario , um para Gerente , um para Diretor , etc. Repare que perder esse poder é muito piordo que a pequena vantagem que a herança traz em herdar código. Porém, em alguns sistemas, como é o nosso caso, usamos uma classe com apenas esses intuitos: deeconomizar um pouco código e ganhar polimorfismo para criar métodos mais genéricos, que seencaixem a diversos objetos. Faz sentido ter uma referência do tipo Funcionario ? Essa pergunta é diferente de saber se fazsentido ter um objeto do tipo Funcionario : nesse caso, faz sim e é muito útil. Referenciando Funcionario temos o polimorfismo de referência, já que podemos receber qualquerobjeto que seja um Funcionario . Porém, dar new em Funcionario pode não fazer sentido, isto é,não queremos receber um objeto do tipo Funcionario , mas sim que aquela referência seja ou um Gerente , ou um Diretor , etc. Algo mais concreto que um Funcionario . ControleDeBonificacoes cdb = new ControleDeBonificacoes(); Funcionario f = new Funcionario(); cdb.adiciona(f); // faz sentido? Vejamos um outro caso em que não faz sentido ter um objeto daquele tipo, apesar da classe existir:imagine a classe Pessoa e duas filhas, PessoaFisica e PessoaJuridica . Quando puxamos umrelatório de nossos clientes (uma array de Pessoa por exemplo), queremos que cada um deles seja ouuma PessoaFisica , ou uma PessoaJuridica . A classe Pessoa , nesse caso, estaria sendo usadaapenas para ganhar o polimorfismo e herdar algumas coisas: não faz sentido permitir instanciá-la. Para resolver esses problemas, temos as classes abstratas.


Like this book? You can publish your book online for free in a few minutes!
Create your own flipbook