Nesse artigo iremos comentar e resolver os exercícios propostos no capítulo 4, sobre Orientação a objetos básica da apostila FJ-11: Java e Orientação a Objetos, da Caelum.
Clique aqui para saber sobre a Caelum e sua apostila.
Enviar um café pro programador
Pode me ajudar a transformar cafeína em código?
Mostrando postagens com marcador Classes e Objetos. Mostrar todas as postagens
Mostrando postagens com marcador Classes e Objetos. Mostrar todas as postagens
Jogo: Campo Minado em Java
Dando continuidade aos games que estamos fazendo, e ensinando a fazer, vamos agora mostrar como fazer e programar o famoso jogo Campo Minado em Java.
Se não acompanhou os outros jogos feitos em nosso curso de Java, veja:
Como fazer o Jogo da Velha em Java
Como fazer o jogo Batalha Naval em Java
Aqui mostraremos as classes e código do jogo, no próximo artigo vamos explicar em detalhes como programar o jogo:
Código comentado sobre a criação do Campo Minado em Java
Como jogar o nosso Campo Minado em Java
Existe um tabuleiro 8x8, onde estão localizadas 10 minas.
A cada rodada você irá fornecer o número da linha e da coluna (ou seja, números de 1 até 8).
A cada rodada você irá fornecer o número da linha e da coluna (ou seja, números de 1 até 8).
Caso exista uma mina naquele lugar, você perde o jogo.
Caso não exista uma mina naquela posição, será exibido número naquele local e números nos locais vizinhos aquele que você escolheu, exceto onde há minas.
Esses números informam quantos minas existem ao redor daquele local.
Por exemplo, se você escolhe um local e aparece o número '2' lá, é porque existem duas minas nas vizinhanças daquele local. Vale salientar que 'ao redor' e 'vizinhança' significam todos os blocos ao redor, incluindo na diagonais.
Objetivo: Deixar os 10 campos que possuem minas livres. Ou seja, onde você deduzir que existe mina, não marque, simplesmente deixe o '_' lá, pois quando existem 10 underlines você ganhará o jogo.
Código do jogo Campo Minado em Java
-->campoMinado.java
public class campoMinado { public static void main(String[] args) { Jogo jogo = new Jogo(); } }
-->Jogo.java
public class Jogo { private Tabuleiro board; boolean terminar = false; boolean ganhou = false; int[] jogada; int rodada=0; public Jogo(){ board = new Tabuleiro(); Jogar(board); jogada = new int[2]; } public void Jogar(Tabuleiro board){ do{ rodada++; System.out.println("Rodada "+rodada); board.exibe(); terminar = board.setPosicao(); if(!terminar){ board.abrirVizinhas(); terminar = board.ganhou(); } }while(!terminar); if(!board.ganhou()){ System.out.println("Havia uma mina ! Você perdeu!"); board.exibeMinas(); } else { System.out.println("Parabéns, você deixou os 8 campos de minas livres em "+rodada+" rodadas"); board.exibeMinas(); } } }
-->Tabuleiro.java
import java.util.Random; import java.util.Scanner; public class Tabuleiro { private int[][] minas; private char[][] tabuleiro; private int linha, coluna; Random random = new Random(); Scanner entrada = new Scanner(System.in); public Tabuleiro(){ minas = new int[10][10]; tabuleiro = new char[10][10]; iniciaMinas(); // coloca 0 em todas as posições do tabuleiro de minas sorteiaMinas(); //coloca, aleatoriamente, 10 minas no tabuleiro de minas preencheDicas();//preenche o tabuleiro de minas com o número de minas vizinhas iniciaTabuleiro();//inicia o tabuleiro de exibição com _ } public boolean ganhou(){ int count=0; for(int line = 1 ; line < 9 ; line++) for(int column = 1 ; column < 9 ; column++) if(tabuleiro[line][column]=='_') count++; if(count == 10) return true; else return false; } public void abrirVizinhas(){ for(int i=-1 ; i<2 ; i++) for(int j=-1 ; j<2 ; j++) if( (minas[linha+i][coluna+j] != -1) && (linha != 0 && linha != 9 && coluna != 0 && coluna != 9) ){ tabuleiro[linha+i][coluna+j]=Character.forDigit(minas[linha+i][coluna+j], 10); } } public int getPosicao(int linha, int coluna){ return minas[linha][coluna]; } public boolean setPosicao(){ do{ System.out.print("\nLinha: "); linha = entrada.nextInt(); System.out.print("Coluna: "); coluna = entrada.nextInt(); if( (tabuleiro[linha][coluna] != '_') && ((linha < 9 && linha > 0) && (coluna < 9 && coluna > 0))) System.out.println("Esse campo já está sendo exibido"); if( linha < 1 || linha > 8 || coluna < 1 || coluna > 8) System.out.println("Escolha números de 1 até 8"); }while((linha < 1 && linha > 8) && (coluna < 1 && coluna > 8) || (tabuleiro[linha][coluna] != '_') ); if(getPosicao(linha, coluna)== -1) return true; else return false; } public void exibe(){ System.out.println("\n Linhas"); for(int linha = 8 ; linha > 0 ; linha--){ System.out.print(" "+linha + " "); for(int coluna = 1 ; coluna < 9 ; coluna++){ System.out.print(" "+ tabuleiro[linha][coluna]); } System.out.println(); } System.out.println("\n 1 2 3 4 5 6 7 8"); System.out.println(" Colunas"); } public void preencheDicas(){ for(int line=1 ; line < 9 ; line++) for(int column=1 ; column < 9 ; column++){ for(int i=-1 ; i<=1 ; i++) for(int j=-1 ; j<=1 ; j++) if(minas[line][column] != -1) if(minas[line+i][column+j] == -1) minas[line][column]++; } } public void exibeMinas(){ for(int i=1 ; i < 9; i++) for(int j=1 ; j < 9 ; j++) if(minas[i][j] == -1) tabuleiro[i][j]='*'; exibe(); } public void iniciaTabuleiro(){ for(int i=1 ; i<minas.length ; i++) for(int j=1 ; j<minas.length ; j++) tabuleiro[i][j]= '_'; } public void iniciaMinas(){ for(int i=0 ; i<minas.length ; i++) for(int j=0 ; j<minas.length ; j++) minas[i][j]=0; } public void sorteiaMinas(){ boolean sorteado; int linha, coluna; for(int i=0 ; i<10 ; i++){ do{ linha = random.nextInt(8) + 1; coluna = random.nextInt(8) + 1; if(minas[linha][coluna] == -1) sorteado=true; else sorteado = false; }while(sorteado); minas[linha][coluna] = -1; } } }
Código comentado sobre como criar um Jogo da Velha em Java
No tutorial passado mostramos um print do Jogo da Velha em Java, modo texto e Humano x Humano, bem como o código de 6 classes necessárias para rodar o programa:
Jogo da Velha em Java
Agora vamos comentar, em detalhes, cada classe, método e idéia que usamos para criar o jogo.
Jogo da Velha em Java
Agora vamos comentar, em detalhes, cada classe, método e idéia que usamos para criar o jogo.
Jogo da Velha em Java
Após estudar Herança, Polimorfismo, Classes e Métodos Abstratos chegou a hora de colocarmos nossos conhecimentos em prática para fazer algo realmente útil e bacana:
um jogo da velha.
Essa é uma versão simples, para ser jogada com duas pessoas. Note que, em uma aplicação Java simples como esta, o resultado saiu por volta de 300 linhas de código.
Mas deixamos as classes e tudo pronto para que, em um próximo tutorial de Java, possamos adicionar o computador em dois modos: modo fácil e modo infalível.
Sim, existe uma estratégia que podemos adotar (ou o computador pode adotar) para nunca perder uma partida de jogo da velha:
http://pt.wikihow.com/Ganhar-no-Jogo-da-Velha
um jogo da velha.
Essa é uma versão simples, para ser jogada com duas pessoas. Note que, em uma aplicação Java simples como esta, o resultado saiu por volta de 300 linhas de código.
Mas deixamos as classes e tudo pronto para que, em um próximo tutorial de Java, possamos adicionar o computador em dois modos: modo fácil e modo infalível.
Sim, existe uma estratégia que podemos adotar (ou o computador pode adotar) para nunca perder uma partida de jogo da velha:
http://pt.wikihow.com/Ganhar-no-Jogo-da-Velha
Manipulando polimorficamente subclasses
Agora que você domina completamente os conceitos de herança, polimorfismo e abstração, vamos aos exemplos práticos - códigos em Java.
Vamos mostrar como é possível uma superclasse abstrata manipule suas subclasses concretas.
Importância do Polimorfismo e Abstração em softwares
O uso dessas duas idéias, ou técnicas, em Java é de vital importância no mundo dos softwares.
Usamos isso o tempo inteiro e nem notamos.
Como programador Java, você deverá ter uma boa capacidade de criatividade e abstração em seus aplicativos.
Vamos mostrar alguns exemplos da utilidade do polimorfismo na abstração em Java.
Usamos isso o tempo inteiro e nem notamos.
Como programador Java, você deverá ter uma boa capacidade de criatividade e abstração em seus aplicativos.
Vamos mostrar alguns exemplos da utilidade do polimorfismo na abstração em Java.
Polimorfismo: Classes abstratas e Métodos abstratos
Desde que iniciamos nossos tutoriais sobre classes e objetos vínhamos tratando as classes como entidades 'reais' ou 'concretas', pois podíamos instanciar objetos a partir dela.Nesse artigo vamos introduzir um conceito importante e bastante útil na orientação a objetos: a abstração.
Pode parecer estranho, ou no mínimo confuso, classificar e utilizar algo que se diz ser abstrato, mas veremos que esse tipo de idéia é bem interessante e bem mais realista que nossa noção antiga de classe e objeto.
Polimorfismo em Java: o que é, pra que serve, como e onde usar
Agora que aprendemos os conceitos mais importantes e vimos o uso da Herança em Java, vamos estudar outra características marcante da programação Java e, de uma maneira mais geral, da programação orientada a objetos: o polimorfismo.
Com o polimorfismo vamos ter um controle maior sobre as subclasses sem ter que nos preocupar especificamente com cada uma delas, pois cada uma terá autonomia para agir de uma meneira diferente.
Com o polimorfismo vamos ter um controle maior sobre as subclasses sem ter que nos preocupar especificamente com cada uma delas, pois cada uma terá autonomia para agir de uma meneira diferente.
A classe Object: o que é, uso e principais métodos
Agora que já sabemos o que é herança, como a herança se comporta em relação aos construtores, uso do @Override e vimos os modificadores de acesso private, public e protected, vamos apresentar uma classe de suma importância bem como alguns de seus métodos: a classe Object.
Herança em Java - o que é, para que serve, exemplos e quando usar
Chegamos em um ponto muito importante em nosso curso de Java no que se refere a Programação Orientada a Objetos.
Herança é uma das maiores características desse tipo tão importante e usado tipo de programação.
Através desse recurso, você irá criar classes de uma maneira bem mais rápida, eficiente e fácil de manter: baseando classes em outras.
Herança é uma das maiores características desse tipo tão importante e usado tipo de programação.
Através desse recurso, você irá criar classes de uma maneira bem mais rápida, eficiente e fácil de manter: baseando classes em outras.
static - Usando membros estáticos em Java
Agora que você sabe a importância das constantes em aplicações Java e como manusear as constantes de seus programas com enum, vamos mostrar uma aplicação mais direta das constantes em nosso estudo de Orientação a Objetos.
Esse artigo Java mostra o uso das variáveis do tipo static, artifício muito usado para manter o controle sobre todos os objetos de uma mesma classe, por exemplo.
Esse artigo Java mostra o uso das variáveis do tipo static, artifício muito usado para manter o controle sobre todos os objetos de uma mesma classe, por exemplo.
Composição: trocando informações entre objetos
Um dos melhores artifícios do Java é a comunicação entre seus elementos, variáveis, métodos, objetos, classes e coisas que verá mais adiante. Mais que isso, o bacana é que podemos controlar essa comunicação, ela pode ser: pública, privada e protegida.
Nesse tutorial, daremos início a essa comunicação, falando sobre a Composição (Composition), que é simplesmente o ato de passar um objeto para outro, para usar seus métodos ou atributos.
O que é Composição em Java
É instanciar, ou usar, uma classe/objeto em outra(o). É como se elas se comunicassem, trocassem informações. Ou seja, serve para reutilizar dados, sem ter que criar mais código pra isso.Simplesmente passamos a informação - na forma de Objeto - para outro Objeto, e este se encarrega de obter os dados e como trabalhar em cima dele.
Costuma-se dizer que composição é o ato de delegar trabalho para outro objeto.
Isso deixa seu código mais elegante, menor e mais seguro.
Para que serve a Composição em Java
Talvez não note muito essa necessidade em projetos pequenos e de iniciantes, mas quando for um profissional, vai ter muita dor de cabeça com isso. Através de uma simplificação de projetos reais, vamos mostrar exemplos de códigos e passaremos exercícios para você notar a importância da Composição em aplicações Java.
Demos o exemplo de setores diferentes em uma empresa naquele artigo inicial.
Dificilmente uma empresa de grande porte vai mandar você fazer e ter acesso a todo o sistema, principalmente o setor financeiro.
Geralmente esse é mantido à sete chaves. Mas como expliquei lá, eles podem simplesmente compartilhar certos dados com você, como o salário final de cada funcionário, para você usar em sua classe "Funcionario".
Notou? Você criar sua classe, faz seu projeto e usa dados de outro Objeto/Classe. E o mais importante: é seguro! Você não faz a mínima idéia do que aconteceu lá, de como é calculado as coisas, dos segredos financeiros da empresa etc.
Graças a orientação a objetos - e outras coisas - isso é possível. Assim você não precisa repetir código.
Além da segurança, a Composição em Java faz com que não seja necessário repetir código. Você simplesmente usa o que já foi feito em outra Classe/Objeto, como é o caso do exemplo da empresa.
Imagina se o programador não soubesse Java? Ia ter que repetir todo o código do setor financeiro dentro da classe "Funcionario"?
Acredite, há coisas bizarras sendo feitas por aí.
Herança x Composição
Mais a frente, em nosso curso online de Java, iremos falar sobre uma das mais importantes, e controversas, e usadas funcionalidades do Java: a Herança. Isso nos leva ao encapsulamento de dados.Não vamos entrar em muitos detalhes agora, mas basicamente herança é capacidade de uma classe herdar dados de outra.
Por exemplo, você cria uma classe mãe. Quer criar uma classe parecida com a mãe - mas com outras funcionalidades, você não precisa reescrever tudo. Basta fazer com que a classe filha herde a classe mãe.
Por exemplo, podemos criar a classe "Carro" quem atributos como "motor", "portas", "carburador" etc, pois todos atributos estão presentes em todos carros. Fazemos então a classe "Fusca" e a classe "Ferrari" herdar a classe "Carro".
Ora, é claro que vamos adicionar mais funcionalidades na classe "Ferrari", pois ela possuir mais atributos que o padrão genérico generalizado da classe "Carro". Mas não deixa de ser um carro.
Essa generalização, o fato de algumas classes herdadas não precisarem de todos os atributos da classe mãe, também devido ao fato de ao se mudar a classe mãe mudar todas as classes filhas e uma porção de outros detalhes, faz com que herança seja um conceito perigoso e não recomendado. Alguns simplesmente abominam a herança.
Não entraremos em detalhe agora, mas usar Composição é inofensivo e bem mais recomendado. Porém, cada caso é um caso.
Exemplo de uso de Composição em Java
Exercício: Descobrindo se um Funcionário chegou atrasado e seu tempo de trabalho.Nesse exemplo, vamos criar 2 classes adicionais: "Funcionario" e "Hora"
Vamos criar um funcionário, o 'geddyLee', criar um objeto para armazenar a hora que ele chegou 'horaChegada' e a hora que ele saiu 'horaSaida'.
A partir da hora de chegada, vamos verificar se ele chegou atrasado (após as 8h) e usando informações dos dois objetos da classe "Hora", vamos saber quanto tempo ele trabalhou e armazenar essa informação na variável "tempoTrabalhado", do objeto 'geddyLee' da classe "Funcionario", e vamos guardar a informação caso ele tenha chegado atrasado
Ou seja, vamos trocar bastante informações entre esses objetos !
controleHorario.java
Essa é nossa classe principal, que tem o método main.Na main, simplesmente criamos os objetos de Hora e Funcionário mencionados no enunciado.
Iniciamos os objetos de "Hora" já com seus valores (hora, minuto,segundo). Você pode mudar a seu gosto, para testes ou pedir ao usuário, através da classe Scanner.
A seguir, a título de informação, ele exibe a hora de chegada, de saída e o tempo total trabalhado em horas.
A main é bem pequena e enxuta, como deve ser.
Hora.java
Essa classe recebe três elementos inteiros: horas, minutos e segundos, e faz um tratamento.O tratamento é: as horas devem ser inteiros entre 0 e 23, os minutos e segundos devem ser inteiros entre 0 e 59.
Caso não seja, é lançada uma excessão (artíficio para mostrar que ocorreu um erro e a aplicação é encerrada).
Experimente colocar uma data errada para ver a mensagem de erro.
Os métodos dessa classe são simples getters um toString().
Método toString()
O método toString é um método especial, existente em todos os objetos de Java (pois está na classe Objects e todas classes são derivadas desta).
Como o nome pode sugerir, ele serve para retornar uma String.
Vamos formatar uma string com argumentos, por isso vamos usar o método format, para exibir as horas, minutos e segundos no formato: hh:mm:ss
Uma outra característica especial deste método é que ele se torna o padrão e automaticamente invocado, caso tente imprimir um 'objeto'.
Isso mesmo, se colocar apenas um objetos em uma função de print, esse método será invocado.
Por isso , para imprimir na main, fizemos apenas:
System.out.println("Hora de chegada: " + horaChegada); System.out.println("Hora de saída: " + horaSaida);
Mas poderíamos ter feito:
System.out.println("Hora de chegada: " + horaChegada.toString()); System.out.println("Hora de saída: " + horaSaida.toString());
Funcionario.java
Essa classe que vai recebe a informação de outros objetos. No caso, ela recebe objetos da classe "Hora".Vamos comentar seus métodos:
- public double tempoAtraso(Hora horaChegada)
Simplesmente transformamos a hora em que o funcionário chegou em segundos:
horaChegada.getHour()*60*60 + horaChegada.getMinute()*60 + horaChegada.getSecond()
E subtraímos do tempo que ele deveria chegar na empresa (8h00min):
8*3600.0
E dividimos por 3600.0, para o resultado ser um double que representa as horas atrasadas.
- public double horasTrabalhadas(Hora horaChegada, Hora horaSaida)
Primeiro, vamos transformar a hora da saída e a hora da chegada em minutos e subtrair esse valor:
(horaSaida.getHour()*60 + horaSaida.getMinute()) - (horaChegada.getHour()*60 + horaChegada.getMinute())
Agora temos a diferença entre os horários de chegada e saída, em minutos.
Então, dividimos tudo por 60.0 para ter o tempo trabalhado, em horas.
Caso esse tempo seja negativo, é porque você colocou uma data de saída anterior a data de chegada.
Então, um erro, com a explicação, é lançado e aplicação é encerrada.
- public double getHorasTrabalhadas()
Código do nosso programa:
controleHorario.java
public class controleHorario { public static void main(String[] args) { Hora horaChegada = new Hora(8, 0, 1); Hora horaSaida = new Hora(9, 30, 0); Funcionario geddyLee = new Funcionario("Geddy Lee", horaChegada, horaSaida); System.out.println("Hora de chegada: " + horaChegada); System.out.println("Hora de saída: " + horaSaida); System.out.printf("Horas trabalhadas: %.1f\n",geddyLee.getHorasTrabalhadas()); } }
Hora.java
public class Hora { private int hours, minutes, seconds; public Hora (int hours, int minutes, int seconds){ //preenchendo as horas if(hours>=0 && hours <24 ) this.hours = hours; else throw new IllegalArgumentException("Hora inválida"); //preenchendo os minutos if(minutes >=0 && minutes < 60) this.minutes = minutes; else throw new IllegalArgumentException("Minutos inválidos"); //preenchendo os segundos if( seconds >=0 && seconds < 60) this.seconds = seconds; else throw new IllegalArgumentException("Segundos inválidos"); } @Override public String toString(){ return String.format("%d:%d:%d", getHour(), getMinute(), getSecond()); } public int getHour(){ return this.hours; } public int getMinute(){ return this.minutes; } public int getSecond(){ return this.seconds; } }
Funcionario.java
public class Funcionario { private String nome; private boolean atraso; private double tempoTrabalhado, tempoAtraso; public Funcionario(String nome, Hora horaChegada, Hora horaSaida){ this.nome=nome; this.tempoAtraso = tempoAtraso(horaChegada); if(this.tempoAtraso > 0) this.atraso=true; if(atraso){ System.out.println("Funcionário '" + this.nome + "' atrasado. "); } this.tempoTrabalhado = horasTrabalhadas(horaChegada, horaSaida); } public double tempoAtraso(Hora horaChegada){ return ((horaChegada.getHour()*60*60 + horaChegada.getMinute()*60 + horaChegada.getSecond()) - 8*3600.0)/3600.0; } public double horasTrabalhadas(Hora horaChegada, Hora horaSaida){ double horas = ( (horaSaida.getHour()*60 + horaSaida.getMinute()) - (horaChegada.getHour()*60 + horaChegada.getMinute()) )/60.0; if(horas < 0) throw new IllegalArgumentException("Hora de saída anterior a hora de chegada"); return horas; } public double getHorasTrabalhadas(){ return this.tempoTrabalhado; } }
Exercício: Aplicativo Java para um Supermercado
Você foi selecionado para criar um aplicativo - em Java, claro - para um supermercado.O que o dono do estabelecimento pediu a funcionalidade "Promoção para você", que funciona da seguinte maneira:
Após as 20h, todos os produtos recebem um desconto de 10%.
Aos sábados e domingos esse desconto vale o dia inteiro.
Ou seja, além de ter uma classe para os produtos do supermercado, você deve criar outra com o horário da compra.
Use a técnica de composition para passar o objeto referente ao horário da compra para o objeto referente ao produto que está sendo comprado. Assim, no objeto produto o preço é calculado com base no horário e dia da semana.
Na sua main, peça o preço do produto, dia da semana e horário da compra (hora, minuto e segundos), e devolva o valor final do produto com base naquele horário.
PS: Em uma aplicação real, não seria necessário fornecer esses dados. Eles seriam obtidos por um leitor de código de barras para saber o preço do produto, e pegaria o horário do sistema, pra preencher os dados referentes ao horário.
Pedimos, porém, por questão de aprendizado, já que você não deve ter um leitor desses em casa...
set e get: o que são e como usar esses métodos de forma correta
Vamos aprender nesta aula de nosso curso online de Java os dois métodos mais usados pelos programadores Java: os getters e setters.
O que são e para que servem os métodos get e set
Eles servem para pegarmos informações de variáveis da classe que são definidas como 'private', porém esses método são definidos como 'public'.
Daí surge uma pergunta natural: por que criar métodos para acessar variáveis, se podemos acessar elas diretamente?
Simples: questão de segurança.
As variáveis 'private' só podem ser acessadas de dentro da Classe. É como se elas fossem invisíveis foram do escopo da classe/objeto. Assim, evitamos que outros métodos, classes ou hackers tenham acesso aos dados de determinada classe, que muitas vezes podem ser dados privados, como é caso de aplicações para empresas e bancos.
Como tratar, então, essas variáveis?
Aí que entra a questão dos métodos. Vamos permitir o acesso a essas variáveis, claro (senão não haveria sentido em usar esses atributos).
Porém, vamos ter um total controle sobre essas variáveis através dos métodos.
Por exemplo: suponha que você tenha que criar uma aplicação para um banco, onde vai limitar o número de saques de um cliente.
Os valores do saldo desse cliente ficarão armazenados na variável 'saldo'. Se você der acesso total a essa variável, o cliente poderia usar de forma descontrolada os serviços do banco.
Porém, podemos criar um método em que, cada vez que o cliente saque dinheiro ele ative um contador:
public void setSaque(double valor){
saldo -= valor;
contador++;
}
Nesse trecho de código, quando o usuário tenta sacar, através do menu do caixa eletrônico, ele vai para o método 'saque()'.
Então cada vez que ele saca, seu saldo diminui em 'valor' e um contador (que é uma variável da classe) é incrementado. É impossível fugir desse método!
Sacou? O contador roda! Sempre!
Sabemos que temos um limite diário de saque, vamos supor que seja três. Então vamos limitar o número de saques:
public void setSaque(double valor){
if(contador <=3){
saldo -= valor;
contador++;
} else {
System.out.println("Você atingiu o limite de saques diários");
}
}
Pronto. Se você sacar 3x, o contador terá valor 4 (supondo que seu valor inicial seja 1), e agora é impossível ele sacar mais, pois sempre vai cair no else.
No próximo artigo criaremos uma aplicação que simula um banco.
Como usar os métodos get e set
Usamos get para obter informações. Esse tipo de método sempre retorna um valor.Usamos set para definir valores. Esse tipo de método geralmente não retorna valores.
Usando o exemplo da classe "Funcionario", do artigo passado sobre this e uso de métodos em Classe e Objetos, temos o código:
getSet.java
public class getSet{ public static void main(String[] args){ String nome = "Neil Peart"; int ID=2112; double salario = 1000000; Funcionario chefe = new Funcionario(); chefe.setNome(nome); chefe.setID(ID); chefe.setSalario(salario); chefe.exibir(); } }
Funcionario.java
public class Funcionario { private String nome; private int ID; private double salario; public void exibir(){ System.out.printf("O funcionário %s, de número %d recebe %.2f por mês", getNome(),getID(),getSalario()); } public void setNome( String nome ){ this.nome = nome; } public void setID( int ID ){ this.ID = ID; } public void setSalario( double salario ){ this.salario = salario; } public String getNome(){ return this.nome; } public int getID(){ return this.ID; } public double getSalario(){ return this.salario; } }
Como invocar métodos de dentro do construtor
Outra maneira de inicializarmos as variáveis de um Objeto, é usando os métodos 'set', direto do construtor:setGet.java
public class setGet{ public static void main(String[] args){ String nome = "Neil Peart"; int ID=2112; double salario = 1000000; Funcionario chefe = new Funcionario(nome, ID, salario); chefe.exibir(); } }
Funcionario.java
public class Funcionario { private String nome; private int ID; private double salario; public Funcionario( String nome, int ID, double salario){ setNome(nome); setID(ID); setSalario(salario); } public void exibir(){ System.out.printf("O funcionário %s, de número %d recebe %.2f por mês", getNome(),getID(),getSalario()); } public void setNome( String nome ){ this.nome = nome; } public void setID( int ID ){ this.ID = ID; } public void setSalario( double salario ){ this.salario = salario; } public String getNome(){ return nome; } public int getID(){ return ID; } public double getSalario(){ return salario; } }
Uso errado do get e set
Qual a diferença entre alterar e pegar o valor de uma variável diretamente (caso ela seja pública), e alterar e pegar o valor dela através de set e get (se ela for privada) ? Não é segurança, já que podemos alterar seu valor como bem quisermos, através dos métodos set.Definir get e set para todas as variáveis, de forma direta, é um exemplo de péssimo hábito de programação. Infelizmente é uma técnica bem comum e muitos programadores, até os mais experientes, cometem esse ato inútil.
Para que servem então? Quando usar?
Só use set e get quando você for fazer algo além de simplesmente mudar o valor de uma variável 'private'.
Lá no começo de nosso tutorial, usamos o exemplo de contador, que limita o número de saques de um cliente a um caixa eletrônico.
Outro exemplo disso, seria em um aplicativo de vendas.
Ao comprar, o método set ou get automaticamente define o valor de desconto ou juros. Assim esse método faz algo mais além do que mudar a variável. Assim, sua aplicação se torna robusta e segura, pois se torna impossível mudar o valor da variável sem que seja alterada o valor do juros ou desconto.
Sempre que seu método set do tipo for:
retorno metodo(tipo valor){
this.nome_da_variavel = valor;
}
Muito provavelmente ele é inútil. Para saber quando usar é simples: use quando for fazer algo além de fornecer valor.
Um exemplo util:
retorno metodo(tipo valor){
this.nome_da_variavel = valor * juros;
};
Vamos treinar!
Exercício: Caixa Eletrônico em Java - Caixa.java
Crie um protótipo de caixa eletrônico em Java. No início, ele pede seu nome e valor $$ inicial que tem na conta. O programa deve fornecer um número de 4 dígitos - número da conta - para o usuário (use Random). Esses dados serão usados para criar um objeto da classe "Conta.java"
A seguir, mostra um menu com as opções (esse menu deverá ser um método):
- Extrato: exibe o nome, número da conta, saldo e quantos saques já foram realizados
- Sacar: recebe o valor a ser sacado, informa se pode ser sacado (não pode ficar negativo) e mostra o saldo
- Depositar: recebe o valor a ser depositado e mostra o novo saldo
- Sair
Esse menu aparece até o usuário escolher sair. As outras opções são métodos que devem fazer parte da "Conta.java" (setters e getters). Note que o usuário pode sacar no máximo 5 vezes por dia.
Solução comentada
Auto-referência com o this - Invocando métodos de Classes e Objetos
No tutorial de Java passado relacionado a Orientação a Objetos, falamos como criar construtores, com ou sem parâmetros, em nossas classes.
Nesta pequena aula, iremos aprender como referenciar membros de um objeto através da keyword 'this', que é uma ferramenta bastante usada por programadores Java em métodos dentro de Classes.
Referenciando membros da classe com this
Se esses dados, dentro da classe são:
private String nome;
private int ID;
private double salario;
E o cabeçalho do construtor é:
public Funcionario( String nome, int ID, double salario)
Como faríamos a atribuição? Ora, do mesmo jeito que fizemos antes:
nome = nome;
ID = ID;
salario = salario;
Epa! Notou que as variáveis da classe e as variáveis do cabeçalho tem o mesmo nome?
E agora, como o Java vai saber que as variáveis da esquerda se referem as variáveis 'private' da classe a as da direita são as que o usuário mandou pra criar o objeto?
Já sei! Basta criar o método com nomes de variáveis diferentes, como fizemos antes:
public Funcionario( String Nome, int id, double Salario){
nome = Nome;
ID = id;
salario = Salario;
}
Ok, isso funcionaria perfeitamente. Mas seria extremamente incômodo, e desorganizado, criar dois nomes pra um mesmo tipo de variável.
Não pode parecer problema agora, com essa simples aplicação. Mas em uma situação real, em que seu programa em Java terá centenas de variáveis e você tiver que criar e decorar nomes de variáveis, isso vai ser um baita problema.
Para isso, existe o 'this', que referencia - ou seja, aponta - a própria classe!
'this' em inglês, significa 'isso', 'isto'. É bem fácil seu uso, veja como ficaria nosso construtor:
public Funcionario( String nome, int ID, double salario){
this.nome = nome;
this.ID = ID;
this.salario = salario;
}
Pronto.
Agora ficou óbvio que 'this.nome' é a variável 'nome' da classe "Funcionario" e 'nome' é a variável que a classe recebeu para criar um objeto!
Usamos o 'this' dentro da classe. Assim, sempre que colocarmos 'this.' antes de uma variável, fica implícito ao Java que estamos nos referindo aos atributos daquela Classe.
Podemos usar, inclusive, em um print, caso esteja dentro da classe. Em um método, por exemplo, como veremos a seguir.
Outra utilidade do 'this' é passar o objeto atual como parâmetro.
public Object getObjeto(){
return this;
}
Outro exemplo disso é criar o método...:
public String toString()
...na sua classe, e usar 'this' dentro de um print. O Java entenderá que deve ser impresso o que estiver dentro desse método 'toString()'.
Outra utilidade do 'this' é invocar outros construtores. Para invocar um construtor dentro de outro, essa chamada deve ser o primeiro comando do construtor atual.
Por exemplo, fazendo simplesmente:
this;
Estamos chamando o construtor padrão, que não recebe parâmetros.
Fazendo:
this(2112);
Estamos invocando o construtor que recebe um inteiro como parâmetro.
Lembrando que quando criamos um construtor que não é o padrão, o Java não vai mais criar o construtor padrão vazio.
Esse construtor padrão vazio só é criado automaticamente quando não criamos nenhum construtor.
Como invocar métodos de objetos que criamos
Vamos criar um método, dentro da classe "Funcionário", que exibe todas as informações de um objeto dessa classe. Vamos chamar de 'exibir':
public void exibir(){
System.out.printf("O funcionário %s, de número %d recebe %.2f por mês", this.nome,this.ID,this.salario);
}
Para invocar, basta colocar '.exibir()' após o nome do objeto, que fará com que este método rode.
Note, porém, que conforme explicamos em nosso artigo sobre Classes e Objetos, essa classe é apenas uma abstração.
Ou seja, esse método não existe de verdade! Ele só vai passar a existir quando criarmos um objeto dessa classe!
(Na verdade ele pode existir, caso a classe fosse estática. Estudaremos isso em breve).
Para ilustrar a chamada de métodos de um objeto e o uso do 'this', vamos criar um funcionário - um objeto - de nome 'chefe'.
O código ficará assim:
thisMetodo.java
public class thisMetodo{ public static void main(String[] args){ String nome = "Neil Peart"; int ID=2112; double salario = 1000000; Funcionario chefe = new Funcionario(nome, ID, salario); chefe.exibir(); } }
Funcionario.java
public class Funcionario { private String nome; private int ID; private double salario; public Funcionario(){ System.out.println("Método construtor padrão invocado!"); } public Funcionario( String nome, int ID, double salario){ this(); System.out.println(this); this.nome = nome; this.ID = ID; this.salario = salario; } public String toString(){ return "Foi usado : System.out.println(this)"; } public void exibir(){ System.out.printf("O funcionário %s, de número %d recebe %.2f por mês", this.nome,this.ID,this.salario); }
Construtor padrão e com parâmetros: o que são, para que servem e como usar
- Você reparou que, no tutorial passado, sobre como declarar e criar classe e instanciar objetos, nós fizemos:
Você reparou como repetimos 'Aluno' duas vezes?
Por que? Não é inútil ou perda de tempo repetir isso?
Em Java - aliás, em programação - nada é à toa (se for, logo eles mudam). Tudo tem um motivo.
Nesse artigo você irá aprender sobre os Construtores (constructors) e saberá o motivo dessa repetição e como usufruir e ganhar muito tempo a partir deles
As explicações e exemplos deste tutorial são baseadas nos outros artigos desta seção:
O que são e para que servem Classes e Objetos em Java
Como criar uma Classe e declarar um Objeto
Acessando e modificando variáveis de Classes e Objetos
O que são construtores/constructor em Java
Quando usamos a keyword 'new' para criar um objeto de uma determinada classe estamos alocando um espaço na memória. Ao fazer isso, o Java requer que algumas variáveis sejam iniciadas com algum valor.Esse ato de inicializar, ou construir, é feito pelos construtores, que são métodos - que iremos estudar mais a fundo em nossa apostila de Java logo mais.
O Java automaticamente inicializa as variáveis globais quando criamos um objeto de uma classe.
No artigo passado de nossa apostila, fizemos um exemplo com a classe "Aluno", onde criamos três variáveis: "nome", "notaMat" e "notaFis", que são consideradas variáveis globais da classe, pois não fazem parte de nenhum método.
Logo, elas devem ser inicializadas pelo Java. Para você ver como isso realmente acontece, vá na sua classe principal, que contém a 'main', e após a criação do objeto "patropi" da classe "aluno" adicione as seguintes linhas de código, de print, para você ver como essas variáveis da classe já possuem um valor, sem nem mesmo você ter atribuído nada:
Aluno patropi = new Aluno();
System.out.println(patropi.nome);
System.out.println(patropi.notaMat);
System.out.println(patropi.notaFis);
O resultado é:
null
0.0
0.0
Ou seja, por padrão, as strings são iniciadas com valores 'null' (nulos) e valores zeros para números.
Isso é o que ocorre automaticamente, quando nenhum construtor é especificado. Vamos mostrar como especificar construtores.
O que é e como utilizar o construtor padrão em Classes
Construtor é um método, em Java.
Embora não tenhamos estudado métodos ainda, diremos como utilizar. É bem simples, e em breve você aprenderá tudo sobre método em nosso curso de Java.
Métodos são um trecho de código que fazem uma coisa específica, em programação. Se já estudou C ou C++, lá eles são chamados de funções ou de rotinas ou sub-rotinas em outras linguagens, como Perl.
Podemos criar vários construtores. O padrão é aquele que não recebe nenhum parâmetro.
Em termos mais simples, é aquele que não recebe nenhuma informação. Ele sempre vai ser executado quando você criar um objeto.
Para criar um construtor, crie um método com o mesmo nome da classe.
Métodos tem a seguinte sintaxe:
nomeDoMetodo( tipoDoParametro nomeDosParametros) {
// código dos métodos
}
Como nossa classe se chama "Aluno", nosso método é um construtor dessa classe e ela é padrão (não recebe parâmetros) e é 'public', ficará assim:
public Aluno(){
}
Para melhor visualizar a utilidade do construtor padrão, vamos adicionar um print:
public Aluno(){
System.out.println("Objeto criado");
}
Ao rodar seu programa, você verá a mensagem "Objeto criado" sendo exibida logo após ter criado o objeto "patropi".
Esse método é chamado construtor default. Ao contrário do que muitos pensam, default não é padrão (embora usemos muito como se fosse).
Default é omissão. Quando estamos omitindo outros construtores - que recebem parâmetro - é esse construtor 'padrão' (default) que será chamado.
Note que ao criar o objeto, usamos "new Aluno();" - logo, não passamos nenhum parâmetro. Então, chamamos claramente o construtor padrão.
Criando um construtor que recebe parâmetros
No nosso aplicativo que cadastro um aluno, seu nome e duas notas, estamos atribuindo os valores dessas variáveis direto no objeto:patropi.nome = entrada.nextLine();
patropi.notaMat = entrada.nextDouble();
patropi.notaFis = entrada.nextDouble();
O que vamos fazer agora, para ilustrar como funciona os construtores que recebem parâmetros, é pedir esses dados antes e iniciar o objeto "patropi" com esses dados.
Por exemplo, vamos criar as variáveis "Nome", "NotaMat", "NotaFis" na 'main' e receber esses dados pela Scanner:
Nome = entrada.nextLine();
NotaMat = entrada.nextDouble();
NotaFis = entrada.nextDouble();
Agora vamos criar nosso construtor na classe "Aluno" que recebe esses três parâmetros: uma string e dois doubles.
Ele vai ficar assim:
public Aluno(String Nome, double NotaMat, double NotaFis){
nome=Nome;
notaMat=NotaMat;
notaFis=NotaFis;
}
Isso pode parecer um pouco estranho ou complicado agora, mas quando estudar melhor métodos, fará todo o sentido do mundo e verá como é simples.
O que esse método faz é receber uma string "Nome", dois doubles "NotaMat" e "NotaFis" e atribuir eles aos valores da classe aluno.
Veja que nossa classe tem uma variável string "nome" e dois doubles "notaMat" e "notaFis", que seriam inicializados com 'null' e '0.0', conforme mostramos no início deste tutorial.
O que estamos fazendo com esse método é inicializar estas variáveis com outros valores! E que valores são estes? Ora, são os valores das variáveis "Nome" e "NotaMat" e "NotaFis", que definimos a partir da classe Scanner no método 'main'.
Embora estejamos engatinhando na orientação a objeto, vamos fazer uma coisa interessante e mostrar o quão poderosa e útil essa técnica é. Vamos adicionar na classe uma variável, um double de nome "media", e no construtor vamos adicionar uma linha de código:
media = (notaMat + notaFis)/2;
Ou seja, nosso construtor vai ficar:
public Aluno(String Nome, double NotaMat, double NotaFis){
nome=Nome;
notaMat=NotaMat;
notaFis=NotaFis;
media = (notaMat + notaFis)/2;
}
O que quer dizer isso?
Que quando iniciarmos nosso objeto com as notas, esse método vai automaticamente calcular a média dessas notas!
Você pode pensar "Mas já fazíamos isso na 'main', durante o print. Não é a mesma coisa?".
Imagine que você vai preencher os dados de 20 alunos.
Então vai colocar 20 vezes essa fórmula? Claro que não.
Aí é que reside a beleza das Classes & Objetos. Você declara essa fórmula uma única vez, e poderá usar ela sempre que criar um objeto!
Criou o objeto, iniciou ele com as variáveis, ele vai calcular automaticamente a média!
Para acessar essa variável basta fazer: patropi.media
E ela estará lá, bonitinha para você usar.
Como iniciar Objetos com parâmetros
Agora que criamos nossos métodos construtores padrão e com parâmetros, vamos mostrar como iniciar um objeto com dados.No construtor padrão, vínhamos fazendo:
Aluno patropi = new Aluno();
Agora, que já temos as variáveis "Nome", "NotaMat" e "NotaFis" e um construtor que está preparado para receber esses três tipos de dados, podemos criar um objeto e lançar essas variáveis:
Aluno patropi = new Aluno( Nome, NotaMat, NotaFis);
Note que você só deve criar esse objeto depois de ter essas variáveis com os valores corretos, senão vai iniciar o objeto com valores errados.
Um detalhe importante é que o nome dessas variáveis, "Nome", "NotaMat" e "NotaFis", não precisam ser iguais aos nomes que declaramos lá no construtor da classe "Aluno". Poderíamos passar:
Aluno patropi = new Aluno( name, math, phys);
Desde que "name" seja uma string e "math" e "phys" doubles. Quando elas 'chegam' no construtor, elas 'chegam' com os nomes "Nome", "NotaMat" e "NotaFis".
Você se acostumará melhor sobre isso quando estudar métodos.
Classes com mais de um construtor
O que ocorre se deixarmos o construtor: Aluno()e o construtor: public Aluno(String Nome, double NotaMat, double NotaFis)
juntos, na classe "Aluno"?
Nada. Aliás, é até recomendável. É um excelente costume.
Se você iniciar um objeto dessa classe sem nenhum parâmetro, o Java inicia o método construtor padrão (que mostra a mensagem "Objeto criado".
Se iniciar um objeto com 3 parâmetros, ele atribui esses valos que você passou aos valores do objeto e ainda calcula a média.
Você pode ainda criar outros métodos, que recebem só o nome do aluno, só a nota de matemática ou só de a física.
Enfim, os construtores são feitos para inicializar os atributos e preparar o objeto para o uso, seja lá qual for o uso que você queira dar. Se você utilizar vários construtores, o Java é inteligente o suficiente para saber qual método utilizar dependendo dos parâmetros que você passar.
Obviamente se criar dois construtores com a mesma lista de parâmetros, terá problemas.
Para mostrar um exemplo do uso de dois construtores - o padrão e o que recebe 3 parâmetros - , vamos criar dois objetos, o "donaFifi", logo no início, e veremos a mensagem "Objeto criado".
Depois pedimos os dados do aluno patropi e inicializamos o objeto "patropi" com esses dados. Em seguida, usamos as variáveis do objeto desse aluno, inclusive sua média, que foi calcula pelo construtor.
Veja como ficou o código:
PrimeiraClasse.java
import java.util.Scanner;
public class PrimeiraClasse {
public static void main(String[] args) {
Aluno donaFifi = new Aluno();
String nome;
Double notaMat,
notaFis;
Scanner entrada = new Scanner (System.in);
System.out.print("Nome do aluno: ");
nome = entrada.nextLine();
System.out.print("Nota em Matemática: ");
notaMat = entrada.nextDouble();
System.out.print("Nota em Física: ");
notaFis = entrada.nextDouble();
Aluno patropi = new Aluno(nome, notaMat, notaFis);
System.out.printf("O aluno \"%s\" tirou %2.2f em Matemática, "
+ "%2.2f em Física e obteve média %2.2f\n", patropi.nome,
patropi.notaMat,
patropi.notaFis,
patropi.media);
}
}
Aluno.java
public class Aluno {
public String nome;
public double notaMat,
notaFis,
media;
public Aluno(){
System.out.println("Objeto criado");
}
public Aluno(String Nome, double NotaMat, double NotaFis){
nome=Nome;
notaMat=NotaMat;
notaFis=NotaFis;
media = (notaMat + notaFis)/2;
}
}
Assinar:
Postagens (Atom)



