1 Orientação a Objetos com Java Para iniciantes Guia rápido e básico para usuários iniciantes na plataforma Java e Orientação a Objetos Yrineu Rodrigues Nooclix – Fábrica de Software 1 1 Sumário de Imagens Figura 1- Criando o projeto __________________________________________________________________________ 6 Figura 2- Criando a classe ___________________________________________________________________________ 7 Figura 3- Inserindo o nome da classe __________________________________________________________________ 7 Figura 4- Código “Olá java”__________________________________________________________________________ 8 Figura 5- Executando o código _______________________________________________________________________ 8 Figura 6- Erro no código ____________________________________________________________________________ 9 Figura 7- Executando o cóidigo com erro _______________________________________________________________ 9 Figura 8- Palavras reservadas do Java _________________________________________________________________ 9 Figura 9- Tipo e nome de variável ____________________________________________________________________ 10 Figura 10- Declarando uma constante ________________________________________________________________ 12 Figura 11- Atribuição composta _____________________________________________________________________ 15 Figura 12- Instanceof ______________________________________________________________________________ 16 Figura 13- Operador Aritmetico _____________________________________________________________________ 16 Figura 14- Operador lógico _________________________________________________________________________ 16 Figura 15- Concatenação e conversão de String ________________________________________________________ 17 Figura 16- Cast Implícito ___________________________________________________________________________ 18 Figura 17- Cast Incorreto ___________________________________________________________________________ 19 Figura 18- Variável de Referência ____________________________________________________________________ 21 Figura 19- Declarando método ______________________________________________________________________ 24 Figura 20- Escopo local ____________________________________________________________________________ 25 Figura 21- Escopo do método _______________________________________________________________________ 26 Figura 22- Utilizando this __________________________________________________________________________ 27 Figura 23- Gerando Getters e Setters _________________________________________________________________ 29 Figura 24- Getters e Setters gerados _________________________________________________________________ 30 Figura 25- Classe _________________________________________________________________________________ 31 Figura 26- Classe Interna ___________________________________________________________________________ 32 Figura 27- Instância vs. Referência ___________________________________________________________________ 34 Figura 28- Enviando objeto por parâmetro ____________________________________________________________ 34 Figura 29- Alterando o construtor ___________________________________________________________________ 35 Figura 30 - Alterando o método toString( ) ____________________________________________________________ 36 Figura 31- Utilizando o método toString( ) modificado ___________________________________________________ 37 2 A História do Java D esenvolvida pelo time conhecido como Green Team da Sun liderado por James Gosling (o pai do Java) em 1992, além de ser uma plataforma e ter uma máquina virtual, é também uma linguagem de programação muito poderosa que segue todos os parâmetros da orientação a objetos, falar de Java e não falar de OO (como é chamada a orientação a objetos) é quase impossível, mas deixaremos esse assuntopara depois, no momento vamos explorar seu contexto histórico. Entre as décadas de 1960 a 1980 as linguagens de programação seguiam um padrão parametrizado, onde não era possível extrair artefatos do mundo real para o ambiente de desenvolvimento, este fato aliado à falta de profissionais capacitados para atender a demanda de requisições de software contribuíram para o surgimento da linguagem Java baseada na madura e bem sucedida linguagem C que de início teve sua aplicação voltada a aparelhos eletrônicos como televisores, aparelho de TV a cabo e vídeo cassete. Em 2009 o Java passou a ser mantido pela empresa Óracle com a promessa de obedecer a estrutura open-source do Java, depois de algumas versões e bastante colaboração de programadores do mundo todo, o Java é uma linguagem madura, bastante segura e com ampla aplicação que atende aos contextos desktop, web e mobile. A Máquina Virtual C omo descrito anteriormente, um dos problemas das linguagens anteriores ao Java era a incapacidade de abstrair elementos do mundo real, outro problema bastante impactante era quando o usuário efetuava a mudança de sistema operacional onde o sistema teria que ser recompilado para poder ser utilizado pelo outro SO. Visando resolver esse problema de uma vez por todas o Java possui uma máquina virtual conhecida como JVM permitindo o desenvolvedor compilar somente uma vez toda a aplicação e utilizá-la em qualquer SO, também conhecido pelo famoso jargão “Write once, run anywhere” (Escreva uma vez, rode em qualquer lugar). O funcionamento da JVM dá-se entre o software e o sistema operacional fazendo uma espécie de tradução do bytecode do sistema gerado pelo compilador , seja ele Linux, Windows, MacOS entre outros, porém cada sistema operacional tem sua própria versão da máquina virtual Java, além de um ótimo gerenciamento de memória. 3 Alguns fóruns destacam que o java é lento ou que é bastante “pesado”, porém atualizações e aprimoramentos na máquina virtual possibilitaram um melhor gerenciamento do bytecode da aplicação garantindo uma ótima performance para a aplicação Java. JIT e Hotspot O utro artifício da JVM é a detecção de pontos quentes da aplicação (partes da aplicação que são usadas com bastante frequência), a JVM decidirá quando será necessário executar essas partes da aplicação possibilitando o uso das funcionalidades somente quando forem realmente necessárias, esse recurso da máquina virtual (que também é um compilador) é conhecido como JIT ou Just In Time (bem na hora). Versões do Java A primeira versão do java 1.0 e a 1.1 traziam consigo bibliotecas bastante significativas como o Java.io e o JDBC, na transição para a 1.2 ocorreu um aumente expressivo na quantidade de bibliotecas da API java, foi quando a Sun teve a ideia de mudar o nome do Java para Java2 com o intuito de diminuir a confusão entre o Java e o Java Script, depois vieram as versões Java2 1.3, 1.4 e Java 1.5, que passou a ser chamado de Java 5 após mudanças significativas na API e por questões de marketing, até o lançamento desta apostila o java está na versão 7 com alterações significativas na estrutura da linguagem e na máquina virtual. Preparando o ambiente de desenvolvimento Agora você já conhece bastante coisa sobre o Java, JVM e como ela funciona, estamos quase prontos para começar a desenvolver e eu sei que você está bastante ansioso para começar a colocar a mão na massa! Mas primeiro é preciso preparar o ambiente de trabalho. Para desenvolver uma aplicação precisaremos de: JDK – Java Development Kit (Kit de desenvolvimento java) contém todas 4 as bibliotecas necessárias para o desenvolvimento de aplicações Java JRE – Java Runtime Environment (Ambiente de execução Java) quando nossa aplicação já estiver pronta para o uso, será preciso instalar na máquina somente o JRE que já contém a JVM, porém não possui as mesmas bibliotecas do JDK, como o nome já diz é somente para execução dos aplicativos Java Alguns programadores com experiências em outras linguagens de programação poderão dizer que o desempenho do desenvolvimento utilizando o Java será menor que se estivesse utilizando outras ferramentas como o delphi e php, porém a escolha de uma linguagem pode variar de projeto para projeto. Faça a escolha que melhor atende seu negócio. 1.1 Entendendo o Eclipse O eclipse é uma IDE (Integrated Development Enviroment) que auxilia no desenvolvimento de aplicações PHP, Java Script, HTML … e claro o Java. A IDE é bastante útil para encontrar erros de sintaxe que impedem o sistema de compilar, existem outras IDE's como o NetBeans e BlueJ, para nossos exercícios e exemplos utilizaremos o Eclipse. Será no elclipse que escreveremos nossos programas gerando arquivos .java (extensão dos arquivos que contêm o código fonte da aplicação), daí o compilador cria os bytecodes de acordo com os arquivos gerados pelo editor e os transformam em .class (extensão da aplicação compilada), após compilar toda a aplicação o carregador lê os arquivos .class que estão armazenados no disco e os carrega para a memória, é onde entra em cena o verificador de bytecode que confirma que não houve nenhuma violação às restrições de segurança do java, por fim a JVM traduz os bytecodes para o sistema operacional que por sua vez carrega toda a aplicação. 5 Olá Java Você já deve está ansioso para criar sua primeira aplicação Java, pois bem vamos dar o nosso olá ao Java com uma simples aplicação que exibe na tela a frase “Olá Java!” Após configurar o nosso ambiente de trabalho com todas as ferramentas que vimos acima, criaremos nosso primeiro projeto indo em File>New>Java Project e informe o nome da aplicação, ex: Ola Java Figura 1- Criando o projeto 6 Clique com o botão direito sobre a pasta “src” dentro do projeto e selecione New>Class para criar uma classe java Figura 2- Criando a classe Figura 3- Inserindo o nome da classe 7 Nomeei a classe com o nome “OlaJava” sem acento e com a primeira letra maiúscula, isso é um padrão da linguagem, ou seja, todas as classes terão que começar com letras maiúsculas, e sem espaços, porém podemos adotar o “CammelCase” expressão dada a nomenclaturas com letras maiúsculas e minúsculas em uma mesma palavra. Após criarmos nossa primeira classe Java já poderemos começar a escrever nossa aplicação. Digite o seguinte código no editor quer irá gerar na tela a frase Olá Java!: Figura 4- Código “Olá java” Figura 5- Executando o código Agora vamos entender o código! Dentro da classe “OlaJava” chamamos o método public static void main(String[] args) {…} que é responsável por executar a aplicação (só pode existir uma chamada ao método main em toda a aplicação), quando o programa é executado a JVM procura a classe que contém a chamada ao método main e sabe que ela é a classe principal e que a partir dela executará toda a aplicação. Dentro do método chamamos outro método o “println” e passamos como parâmetro a frase que queremos mostrar na tela (falaremos sobre passagem de parâmetros e métodos mais a frente). 8 2 Indicadores e palavras-chaves Assim como toda linguagem de programação, o Java possui suas restrições quanto à escrita do código fonte, por exemplo, se esquecermos de colocar o ponto e vírgula no final da declaração System.out.println( ) e tentarmos executar a aplicação será lançado o seguinte erro: Figura 6- Erro no código Figura 7- Executando o cóidigo com erro 2.1 Palavras-chaves Palavras chaves são palavras reservadas da linguagem, no nosso caso, as palavras reservadas do java são as citadas a seguir: Figura 8- Palavras reservadas do Java 9 Essas palavras-chaves não podem ser usadas para nomear classes, métodos, ou variáveis, as IDE's ajudam o desenvolvedor a se precaver desses erros na hora da construção de um projeto avisando ao mesmo que o nome é uma palavra reservada da linguagem. 2.3 Tipos primitivos Toda variável no java tem um tipo e um nome. Figura 9- Tipo e nome de variável Podemos dividir as variáveis do Java em dois tipos, os tipos por referência e tipos primitivos onde temos como tipos primitivos byte, short, long, boolean, int, char, double e float. Uma variável primitiva só pode armazenar um valor por vez, um exemplo disso é uma variável do tipo double (ex: 0.2), ao adicionar um valor a uma variável do tipo double e em seguida atribuir outro valor (ex: 2.3), o valor inicial será substituído, por isso que ao criar variáveis do tipo primitivo elas receberão valores padrões, onde char, byte, short, long, int, double e float, receberão valor 0(zero) já as variáveis do tipo boolean iniciarão como false, porém nada o impede de atribuir um valor inicial a uma variável, respeitando o tipo que ela recebe claro, lembrando que as variáveis locais não são inicializadas por padrão! O java é uma linguagem fortemente tipada, isso quer dizer que ao declarar uma variável é preciso informar o tipo da mesma e que ela só receberá valores do tipo que foi declarada. 10 Quando nos referimos a variáveis de escopo local estamos falando de variáveis que foram declaradas dentro do corpo de algum método, já quando falamos em variáveis de escopo global estamos nos referindo a variáveis declaradas no escopo da classe, fora de qualquer método! Ao tentar utilizar uma variável local sem inicializá-la causará um erro de compilação! Tipos por referência são utilizados para armazenar os endereços dos objetos na memória do computador, sendo assim os objetos podem conter outras variáveis de instância e até mesmo métodos, quando uma variável de referência não “aponta” para nenhum objeto ela recebe o valor null, indica que essa variável está vazia. Algumas pessoas por estarem iniciando seus estudos em java se perguntam se uma variável declarada como String é um tipo primitivo, que neste caso é uma referência à classe String do pacote java.lang. Aqui vai uma dica, todo tipo por referência inicia o tipo da variável com letra maiúscula, ex: String nome; Pessoa p2; 2.4 Constantes Vimos como declarar variáveis de tipo primitivo e tipo por referência, agora iremos um pouco mais a frente explicando um conceito bastante utilizado no Java, o uso das constantes. Sempre que falamos em constante nos remete a algo que nunca varia de estado, e como a Orientação a Objetos abstrai conceitos do mundo real podemos definir que uma constante em java é uma variável ou um comportamento (método) que nunca altera seu estado. 11 Para definir uma constante no java utilizamos a palavra reservada final na declaração do método ou variável, ex: Figura 10- Declarando uma constante O mesmo acontece para os métodos, porém de forma um pouco diferente, se declararmos um método como final, o mesmo não pode ter seu estado alterado em uma subclasse da classe onde o método foi declarado, caso contrário irá lançar um erro informando que o método declarado na subclasse não pode sobrescrever um método final declarado em uma superclasse(não se preocupe agora com os termos superclasse ou subclasse, iremos falar sobre isso mais a frente). Também, podemos ter classes declaradas como final porém a particularidade delas é que não podem ser herdadas e todos os métodos declarados em uma classe tida como final também serão constantes. 12 3 Operadores Na linguagem java possuímos operadores distintos para cada tipo de situação, como os exemplificados na tabela: Operador = De atribuição Atribuir valore a uma variáveis += Incrementa e atribui -= Decrementa e atribui =+ Atribui e depois incrementa =- Atribue e depois decrementa Aritmético + Soma - Subtração * Multiplicação / Divisão % Mod (resto) ++ Incrementa um ao valor atual -- Subtrai um do valor atual Comparação < <= > Menor que Menor que e igual Maior que >= Maior que e igual == Igual a != Diferente de Instanceof Compara a instância do objeto com uma classe Lógicos 13 || && ! Or (ou uma opção ou outra) And (uma opção e outra) De negação Outros + Também usado para concatenar Strings *Existem outros operadores lógicos conhecidos como Bitwise, porém não são comumente utilizados 3.1 Operadores de atribuição Quando atribuímos um valor a uma variável estamos alterando o valor original da mesma seja ela um tipo primitivo ou de referência, então fazemos uso do sinal de igualdade (=), lembrando que uma variável de referência não é um objeto e sim a maneira de se chegar a um, da mesma forma que não pode ser vista como um ponteiro, pois diferente do C++ o java não possui ponteiros. Lembre-se que ao atribuir à variável de referência o tipo do valor faz toda a diferença, por exemplo: Não podemos atribuir um valor do tipo String a um valor do tipo inteiro. 14 3.2 Operadores e atribuição compostos: Existem 11 tipos de operadores compostos, mas somente quatro são utilizados, são eles: (+=, -=, *= e /=), eles nos permitem dar uma descansada nos dedos economizando algumas digitadas de código, ex: Figura 11- Atribuição composta 3.3 Operações de comparação Comumente são seis operadores de comparação, são eles: (<,<=,>,>=,== e !=), onde seu objetivo é sempre resultar em valores booleanos, vejamos o exemplo abaixo: Estes operadores são usados geralmente em instruções de controle (não se preocupe agora em entender instruções de controle, iremos abordar mais a frente). Já o operador Instanceof somente é usado para variáveis de referência para verificar se um objeto é de um tipo específico (quando falamos em tipo, estamos nos referindo a interface ou classe), por isso o instanceof é também um operador de comparação, onde o resultado é um boolean veremos o exemplo abaixo: 15 Figura 12- Instanceof 3.4 Operadores aritméticos Os operadores aritméticos são bastante conhecidos e são usados para efetuar cálculos matemáticos básicos, ex: Figura 13- Operador Aritmetico 3.5 Operadores lógicos Os operadores lógicos são bastante utilizados em blocos condicionais onde precisamos de resultados booleanos para uma tomada de decisão. Além do operador &&(and) temos o ||(or) e !(not). Figura 14- Operador lógico 16 3.6 Operador de concatenação de Strings (+) Uma particularidade dos tipos Strings é a forma como é tratada a concatenação entre um tipo String e outra variável, seja do tipo primitivo ou por referência, o resultado é uma nova String, onde à um *cast automático para o tipo String. Cast é uma forma de converter os tipos das variáveis, por exemplo, se tenho uma variável do tipo inteiro posso convertê-lo para um double. Veremos cast no próximo ponto, continue lendo! Figura 15- Concatenação e conversão de String Verifique que na primeira impressão de texto fizemos uma soma (usamos um operador aritmético), já na segunda impressão fizemos uma concatenação entre uma String e uma possível soma de inteiros, porém houve uma conversão do tipo inteiro (int) para o tipo String, por isso temos como resultado o valor 31 (apenas juntou as Strings) 17 4 Casting Nos tópicos acima vimos um ótimo exemplo de casting, mas agora iremos aprofundar um pouco mais nos conceitos de casting. Quando falamos em Cast, podemos facilmente entender como uma conversão, onde pode ser uma conversão implícita ou explícita. Implícita é quando não precisamo escrever um código para efetuar a conversão(cast), em outras palavras, temos uma conversão implícita quando inserimos um item menor em outro maior (quando colocamos um número do tipo int em uma variável do tipo double), já a conversão explícita é o contrário, onde temos que escrever o código responsável pela conversão dos dados. Para entender melhor, vamos para os exemplos: Figura 16- Cast Implícito Na linha 5, definimos o valor da variável i com os números 123, de forma implicita, fizemos um cast do valor int para float (ou seja, tiramos os números 123 de um contêiner menor para um outro maior, que no caso é o float. Assim como item de contêiner menor pode ser convertido para um contêiner maior, podemos fazer o contrário com a ajuda da conversão explicita, como no exemplo abaixo: Ao convertermos a variável d do tipo double (variáveis do tipo double aceitam valores decimais) para o tipo int, temos a “perda” do valor depois do ponto, pois o tipo int não reconhece valores decimais, por isso que quando mostramos o valor de i são mostrados somente os números 123. Para esse caso, não podemos ter uma conversão implícita, pois a mesma implicará no seguinte erro: 18 Figura 17- Cast Incorreto Na linha 8, estamos tentando fazer uma conversão implícita do tipo double para o tipo int, isso não será possível, pois o contêiner double é maior que o contêiner int, onde nesse caso estamos tentando colocar todo o valor dcecimal dentro da variável i. Também tempos um cast implícito, quando concatenamos variáveis com uma String, automaticamente ocorrerá uma conversão para o tipo String. Tome atenção ao concatenar um atributo com outro do tipo String, pois o resultado pode não ser o esperado! 19 Orientação a objetos A ntes de falarmos em orientação a objetos vamos voltar um pouco antes de surgir a OO e entender como se dava a programação modular. Uma das alternativas de sanar os problemas provenientes da Programação Orientada a Procedimentos foi a programação modular, que tem como objetivo dividir a aplicação em vários módulos fazendo a combinação entre dados e procedimentos, a ideia era ocultar detalhes internos do restante do programa (veremos que na OO isso chama-se desacoplamento do código, veremos mais a frente), porém alguns problemas foram encontrados como por exemplo a visibilidade dos atributos da aplicação, podendo alterá-los em qualquer lugar, outro problema era quanto à prática do reuso de código. Um exemplo de linguagem modular é o C que incorpora os módulos por meio da definição de tipos abstratos de dados com o uso do operador struct. Visando atender a um mercado bastante crescente e com o objetivo de simular situações reais surgiu a POO (Programação Orientada a Objetos) onde permite a criação de uma abstração do cotidiano e implantar soluções que atendesse a problemas reais. Uma das particularidades da OO é a visibilidade de atributos e comportamentos do sistema impedindo alterar seu estado ou tipo. Com esse avanço foi possível modelar os sistemas de forma análoga aos problemas do mundo real, assim como a redução nos custos de fabricação e manutenção das aplicações. A OO adiciona conceitos novos à programação modular, como a herança e o polimorfismo deixando de ser dividido em módulos/procedimentos e passando a ser divido em classes/objetos. Também houve alteração no fluxo do programa, que deixou de ser sequencial e passou a ser por interações entre os objetos. 20 5.1 Atributos Como vimos nos exemplos dos capítulos anteriores, atributos podem ser de tipo primitivo ou por referência e é essencial diferenciarmos os dois. Variáveis declaradas como do tipo por referência são usadas para salvar o endereço de memória do objeto. Quando temos um objeto instanciado na memória (não se preocupe agora a palavra instanciado, iremos abordá-la mais a frente) e precisamos tratar esse objeto (alterar seu estado ou recuperar algum dado) temos que “guardá-lo” em uma variável de referência do mesmo tipo do objeto, como fazemos com variáveis do tipo String, vejamos o exemplo: Figura 18- Variável de Referência Como podemos observar, alteramos o valor da variável “variavelString” do tipo String passando como valor a frase “Olá java!” e em seguida mostramos seu valor fazendo apenas uma chamada à variável. Para manter a organização do código tente seguir um padrão, uma das melhores práticas de programação é adotar o uso do cammel case nos nomes das variáveis inserindo letras maiúsculas e minúsculas (ex:nomeDaVariavel), evite iniciar o nome da variável com letra maiúscula e nunca utilize acentos ou espaços. 21 Para declarar atributos no Java, devemos seguir alguns padrões da linguagem, diferente da linguagem Pascal e do Action Script não precisa inserir antes da variável o operador VAR, bastando apenas informar a visibilidade, o tipo e o nome da variável. private String str; <visibilidade> <tipo> <nome>; 5.2 Modificadores de acesso Como vimos, um dos preceitos da OO é a atenção à visibilidade dos atributos e métodos de uma classe. Os tipos de modificadores de acesso podem ser public, private, protected e default. Public: Definir variáveis com acesso público fará com que a mesma seja visualizada em qualquer lugar do código, não é boa prática definir todas as variáveis do código como pública, isso estará ferindo o conceito de segurança do código. Quando falamos em segurança do código estamos nos referindo a você programador, onde são adotadas medidas que “esconde” os atributos e métodos das outras partes do código. Private: Membros marcados com o modificador private não podem ser acessados por outras classes do código. Já a classe que declarou o membro private terá acesso total ao atributo ou método. 22 Protected e Default: Apesar de serem bastante idênticos, cada um tem sua particularidade. O modificador protected é utilizado para permitir acesso somente a classes do mesmo *pacote, classes de pacotes diferentes não conseguem visualizar diretamente esses membros declarados como protected. Já o modificador default permite acesso somente a classes do mesmo pacote, sendo assim, classes de pacotes diferentes não conseguem visualizar membros default. Então pelo que ficou entendido, o protected e o default têm o mesmo propósito? ◦ A particularidade do membro protected dá-se pela capacidade de poder visualizar membros protected em subclasses de outros pacotes, já os membros default não podem ser visualizados de forma alguma por classes de outros pacotes! Ótimo, estamos começando a entrar em conceitos bastante empolgantes do java e da OO, por isso não se preocupe agora com o termo subclasse o u superclasse, iremos abordá-los logo logo! Outra particularidade da OO e da linguagem java é que NÃO podemos aplicar modificadores de acesso em variáveis de escopo local, somente em variáveis de escopo global. Lembrando que variáveis de escopo global são variáveis declaradas fora dos métodos, dentro da classe. Já variáveis locais são declaradas dentro de métodos. 23 Visibilidade Public Private Protected Default Em subclasses do mesmo pacote Sim Não Sim Sim Em qualquer classe do mesmo pacote Sim Não Sim Sim Dentro da mesma classe Sim Sim Sim Sim Em outro pacote Sim Não Sim (pela herança) Não Em subclasses do mesmo pacote Sim Não Sim Sim 5.3 Métodos Ao falarmos em métodos lembre-se sempre de comportamento, pois como trabalhamos com OO, os métodos definem o comportamento do objeto. Todos os métodos devem ser declarados no escopo da classe interagindo com variáveis globais ou locais. Um exemplo clássico em livros de Java com OO, é o exemplo do cachorro, que tem funções(métodos) próprios, como por exemplo latir, andar, uivar e etc. Esses métodos irão definir e de certa forma especializar aquele objeto, podendo assim haver interações entre os métodos declarados em uma classe. Figura 19- Declarando método 24 Agora vamos entender essa parte do código e o método declarado. Na linha 5 definimos primeiramente o modificador de acesso desse método, que no caso é public, ou seja, o método latir pode ser acessado em qualquer lugar do código, após o modificador de acesso definimos o tipo do retorno (lembre-se que sempre que for declarar qualquer método deve-se informar o tipo de retorno dele), nesse caso definimos o retorno como void, significa que o método não irá retornar nenhum valor, retornar? Mas para quem?? Quando chamamos um método em qualquer lugar do código, esse método pode retornar algum resultado, como um objeto ou um resultado de uma soma qualquer, vejamos o exemplo: Figura 20- Escopo local Observe que na linha 5 alteramos o tipo de retorno do método de void para String, o que nos obriga agora a retornar um valor String, agora qualquer elemento do código que chamar o método latir receberá a variável latido e seu respectivo conteúdo Miau!?!?. Podemos também ter métodos declarados como static, que podem ser acessados em qualquer lugar do código chamando apenas a classe e o método, sem precisar de uma variável de referência! Continue estudando, iremos abordar esse assunto mais a frente. 25 Em várias partes dessa apostila falamos em variáveis de escopo local e variáveis de escopo global, pois bem essa é a melhor hora de exemplificar esses dois tipos: Lembre-se sempre, o nome do método nunca pode iniciar com números, existem outras regras, pesquise sobre essas regras, vale a pena! Figura 21- Escopo do método Tudo que está entre “{e}” do método é tido como local, por exemplo a variável latido está definido dentro do método latir(), isso quer dizer que essa variável só pode ser acessada dentro do método latir(), não podendo assim outro método definido na mesma classe acessar essa variável ou qualquer outra que venha a ser declarada dentro do método. Já como podemos ver no exemplo, o escopo global é todo o espaço da classe, onde definimos os métodos e variáveis que poderão ser acessadas ou modificadas por qualquer método dentro da classe. 26 Outra particularidade dos métodos é que podemos informar quando um método irá receber algum valor como parâmetro Observe que na linha 5 declaramos a variável String latido no escopo de passagem de parâmetro, agora o método latir( ) espera receber como parâmetro algum valor do tipo String, a partir de agora, quando fizermos uma chamada ao método latir( ) em qualquer parte do código, seremos obrigados a passar como parâmetro um valor String ou um valor null. Quando passamos como parâmetro o valor null, estamos enviando uma referência nula para a variável do tipo String, pois como vimos anteriormente, String é uma classe e não um tipo primitivo! O null quer dizer que essa variável não aponta para nenhuma referência ou objeto! Essa também é a melhor hora para falarmos da propriedade this, pois está totalmente ligado à variáveis de escopo global, local e consequentemente à métodos e passagem de parâmetros. Figura 22- Utilizando this 27 Com a palavra-chave this podemos referenciar dentro de um método uma variável definida no escopo global. Porém nesse caso se retirarmos o this referenciamos a variável novoLatido do mesmo jeito. Então qual a utilidade do this? Uma boa prática de desenvolvimento de software é declarar variáveis com nomes que têm haver com o contexto, sendo assim uma boa prática declararmos apenas a variável latido fora do escopo do método e fazer uma referência a essa variável através do this Exclusivamente nesse caso, se retirarmos o this iremos nos deparar com um erro de lógica, onde estaremos processando somente a variável de escopo local. Uma variável declarada no escopo de passagem de parâmetro é vista pelo método como uma variável local e só poderá ser tratada dentro do corpo do método! 5.4 Métodos get( ) e set( ) Falamos no começo dessa apostila sobre modificadores de acesso, e nos deparamos com o modificador private, agora que falamos de métodos podemos encontrar uma maneira de trabalhar com essas variáveis privadas. Uma boa prática de desenvolvimento e peça chave da OO é o encapsulamento, você já deve ter ouvido falar sobre esse assunto em algum lugar, pois quando falamos de OO é quase que impossível não falar de encapsulamento, porém iremos nos aprofundar nesse assunto mais a frente, até agora só precisamos saber que declarar variáveis ou métodos como private é uma prática que mantém o encapsulamento do código. Você deve estar se perguntando como irá acessar essas variáveis privadas em outras classes! Porém a solução estão nos métodos get() e set() onde o método get() apenas retorna um atributo e o método set() altera o valor do atributo, dessa forma podemos chamar esses métodos para ter acesso a essas variáveis 28 Algumas pessoas poderão dizer que não gosta de Java por conta do encapsulamento e dos vários caminhos que devemos percorrer para alterar ou ler o valor de alguma variável, mas isso é o “charme” dessa linguagem e da OO com a prática, você se sentirá “obrigado” a sempre programar dessa forma. Agora, só poderemos ter acesso em outra classe à variável latido por meio dos métodos getLatido( ) e setLatido( ). Na IDE eclipse, temos um atalho que nos auxilia a declarar de forma automática os métodos get( ) e set( ): Figura 23- Gerando Getters e Setters Clique com o botão direito em cima do código, repouse o mouse em cima de source e selecione a opção Generate Getters an Setters, será mostrado uma tela com os atributos, daí você pode selecionar qual método deseja criar. 29 Figura 24- Getters e Setters gerados 5.5 Classes Gosto muito de dar um exemplo bastante prático e também bastante usado em livros de Java e OO para definir Classe em Java. Podemos ver uma Classe com um molde ou uma planta de uma casa, onde contém os atributos e comportamentos dos objetos, por exemplo: Quando vamos fazer uma casa, primeiro projetamos o que irá compor essa casa e quais funções terão cada parte da casa para depois poder usar essa planta e fazer casas no mesmo padrão, porém em lugares diferentes (lógico). Do mesmo jeito é feito com o java, declaramos uma classe com seus atributos e métodos, para depois usá-la como um molde para contruir objetos com as mesmas funções e atributos, só que estarão em lugares diferentes. Agora ficou claro? Se não ficou ainda, vamos exemplificar em java para você entender melhor. Em outras palavras, uma classe é o arquivo onde tudo será declarado. 30 Figura 25- Classe Porém como vimos em atributos e métodos, as classes também podem ser public ou default, mas nunca private ou protected* Podemos ter classes private ou protected quando definimos uma classe interna, mas esse conceito iremos tratar mais a frente! Como vimos no começo dessa apostila, uma classe deve sempre ser declarada com a primeira letra maiúscula, essa padronização nos ajuda a identificar quando estamos referenciado uma classe ou um tipo primitivo. Também podemos ter classes dentro de outras classes, denominadas como classes internas, essas classes têm seu acesso ainda mais restrito, sendo acessada somente no escopo da classe que a encapsula. 31 Figura 26- Classe Interna Repare que a classe Cachorro está declarada dentro do escopo da classe Animal, na linha 4 declaramos uma variável nome do tipo String, essa variável poderá ser acessada tanto dentro da classe Animal quanto em Cachorro, porém a variável patas do tipo int(integer) só poderá ser acessada dentro da classe Cachorro. Também existe outro conceito parecido com classes internas, são as classes anônimas, mas não iremos abordar nessa apostila, porém vale a pena pesquisar sobre o assunto! 5.6 Objetos Agora que já conhecemos o que é uma classe, estamos aptos a entender o que é um objeto. Vimos que as classes são os moldes, mas moldes são usados para fabricar alguma coisa, para fabricar essa “coisa” precisamos de um construtor, no caso da casa, precisaremos dos pedreiros, no caso do java precisaremos do NEW, essa palavra reservada tem o poder de criar objetos, transformar meras variáveis de referência em variáveis de instância, você já deve ter ouvido esse termo em algum lugar, porém é comum fazer confusão entre variável de referência e variável de instância. 32 Verifique que na linha 4 estamos declarando uma variável do tipo Cachorro e logo após na mesma linha estamos fazendo uma chamada ao construtor da classe cachorro, que irá construir de fato o objeto cachorro, é nessa hora que damos “vida” ao nosso objeto e podemos usar todos os seus métodos e atributos* Lembre-se de que só podemos ter acesso a membros private por intermédio de métodos! Ao instanciar um objeto estamos ocupando um espaço na memória do computador, o mesmo receberá um endereço correspondente à sua localização na memória, quando declaramos uma variável de referência, por padrão ela recebe como valor null o que indica que ela não aponta para nenhum espaço de memória do computador, ou seja ela não é um objeto. 33 Figura 27- Instância vs. Referência Esse “@19ee1ac” é o endereço de memória do objeto. Legal isso não? Com isso podemos ter objetos distintos porém com comportamentos diferentes, um outro exemplo muito bom para isso somos nós, onde todos possuímos RG, CPF, idade, altura, peso, mas somos pessoas com características distintas, ou seja os objetos terão os mesmo atributos e métodos, porém com valores diferentes. Com o advento da OO, podemos passar objetos por parâmetro de métodos, por exemplo: Figura 28- Enviando objeto por parâmetro 34 Na linha 5 da classe Animal, declaramos o método receberOGato(Gato gato), que receberá como parâmetro uma variável do tipo Gato, para ter acesso a esse método instanciamos uma variável animal do tipo Animal na linha 6 da classe cachorro e enviamos como parâmetro o objeto gato do tipo Gato. Como afirmamos anteriormente, podemos ter objetos com comportamentos e atributos iguais, porém com valores diferentes, mas também podemos ter ações pré definidas ao instanciar uma variável, alterando apenas o construtor como no exemplo abaixo: Figura 29- Alterando o construtor Na linha 6 da classe Gato declaramos um construtor de Gato. 35 5.7 ToString( ) É quase impossível falar sobre o método toString e não falar de herança ou polimorfismo, mas deixaremos esses dois tópicos para mais a frente, agora o que precisamos saber sobre o método toString( ), é que toda classe que herda de Object tem o método toString( ) e em Java, toda classe quando criada, automaticamente recebe por herança o método toString( ). A ideia central do toString( ) é que você obtenha alguma representação de determinado objeto. Não entendeu? Para entender melhor, vamos alterar a classe Gato( ) do exemplo anterior, que ficará da seguinte forma: Figura 30 - Alterando o método toString( ) Entre as linhas 15 e 19 temos a declaração do método toString() que foi reescrito para adicionar um valor à variável sobrenome com o valor “Gato”, a particularidade do método toString() é que todas as classes têm esse método implicitamente e pode ser acessado a partir de qualquer objeto, no nosso caso é o objeto gato, em outra classe que instânciar um objeto do tipo Gato, poderá acessar o método toString() e mostrar o valor delclarado na classe Gato. Para enfatizar o que falamos acima, ao instânciar um objeto do tipo Gato, conseguimos mostrar o valor Gato que é justamente o valor que o método toString() retorna, que é o “sobrenome” do gato. Agora façamos o seguinte teste: Apague o método toString() da classe Gato e coloque para executar a classe Cachorro (que contém o método main), o resultado será algo parecido com este: 36 Figura 31- Utilizando o método toString( ) modificado Dessa vez mostramos o endereço de memória do objeto gato, que só foi possível porque o método toString() está declarado na classe Object e como toda classe em Java herda de Object, é feita uma chamada implícita ao método toString() da mesma, que por padrão tem a função de mostrar o endereço de memória do objeto, por isso que afirmo novamente, que o método toString() tem a responsabilidade de mostrar alguma representação significativa de determinado objeto. 37 Na próxima edição da apostila teremos: Conexão com banco de dados utilizando JDBC Tratamento de exceção Estruturas de Controle Estrutura de Repetição Entre outros... Caro amigo programador, caso tenha dúvidas ou sugestões, por favor, entre em contato pelo email [email protected], caso tenha alguma opinião sobre novos assuntos para futuras edições da apostila, estas serão muito bem vindas. Espero que este material possa lhe ajudar em seus estudos sobre Java e OO. Atenciosamente, Yrineu Rodrigues – Nooclix Fábrica de Software 38