In [ ]:
public class GarotoZumbi
{
int idade;
String estado;
String nome;
public GarotoZumbi(int pIdade, String pEstado, String pNome) {
idade = pIdade;
estado = pEstado;
nome = pNome;
}
public void mostra() {
// cabeleira
if (idade >= 2)
System.out.println(" *");
// corpo com olhos
if (estado.equalsIgnoreCase("acordado"))
System.out.println(" o*o");
else
System.out.println(" -*-");
// barba
if (idade >= 3)
System.out.println("*****");
System.out.println(nome);
System.out.println();
}
public void cresce() {
if (idade < 3)
idade++;
mostra();
}
public void acorda() {
estado = "acordado";
mostra();
}
public void dorme() {
estado = "dormindo";
mostra();
}
}
GarotoZumbi garoto = new GarotoZumbi(1, "acordado", "Asdrubal");
garoto.mostra();
garoto.dorme();
garoto.cresce();
Um objeto pode fazer referência à própria instância usando o this
. Este termo indica uma referência ao próprio objeto dentro dele mesmo.
No construtor da versão acima foi usado o nome do parâmetro diferente do atributo para que não haja confusão.
public GarotoZumbi(int pIdade, String pEstado, String pNome) {
idade = pIdade;
estado = pEstado;
nome = pNome;
}
Entretanto, é possível (e comum) o uso do mesmo nome (parâmetros e atributos), com a diferenciação sendo feita pelo this
. Veja como o construtor é modificado:
public GarotoZumbi(int idade, String estado, String nome) {
this.idade = idade;
this.estado = estado;
this.nome = nome;
}
Quando não há indicação do escopo da variável, o Java dá sempre prioridade ao escopo mais interno. Portanto, quando indicamos apenas idade
ele entende que é o parâmetro (escopo mais interno). Já this.idade
indica o atributo especificado explicitamente.
Veja o código completo a seguir:
In [ ]:
public class GarotoZumbi
{
int idade;
String estado;
String nome;
public GarotoZumbi(int idade, String estado, String nome) {
this.idade = idade;
this.estado = estado;
this.nome = nome;
}
public void mostra() {
// cabeleira
if (idade >= 2)
System.out.println(" *");
// corpo com olhos
if (estado.equalsIgnoreCase("acordado"))
System.out.println(" o*o");
else
System.out.println(" -*-");
// barba
if (idade >= 3)
System.out.println("*****");
System.out.println(nome);
System.out.println();
}
public void cresce() {
if (idade < 3)
idade++;
mostra();
}
public void acorda() {
estado = "acordado";
mostra();
}
public void dorme() {
estado = "dormindo";
mostra();
}
}
GarotoZumbi garoto = new GarotoZumbi(1, "acordado", "Asdrubal");
garoto.mostra();
garoto.dorme();
garoto.cresce();
Como será visto posteriormente, as classes elas controlam o acesso aos seus atributos e métodos. Isso permite que a classe decida o que é publicado.
O controle de acesso é feito por modificadores como private
(visível apenas dentro da classe) e public
(visível fora da classe).
As boas práticas da Orientação a Objetos indicam que atributos devem ser privados e métodos publicos, como na implementação a seguir.
In [ ]:
public class GarotoZumbi
{
private int idade;
private String estado;
private String nome;
public GarotoZumbi(int idade, String estado, String nome) {
this.idade = idade;
this.estado = estado;
this.nome = nome;
}
public void mostra() {
// cabeleira
if (idade >= 2)
System.out.println(" *");
// corpo com olhos
if (estado.equalsIgnoreCase("acordado"))
System.out.println(" o*o");
else
System.out.println(" -*-");
// barba
if (idade >= 3)
System.out.println("*****");
System.out.println(nome);
System.out.println();
}
public void cresce() {
if (idade < 3)
idade++;
mostra();
}
public void acorda() {
estado = "acordado";
mostra();
}
public void dorme() {
estado = "dormindo";
mostra();
}
}
GarotoZumbi garoto = new GarotoZumbi(1, "acordado", "Asdrubal");
garoto.mostra();
garoto.dorme();
garoto.cresce();
In [ ]:
System.out.println(garoto.idade);
garoto.nome = "Asdrubal Silva";
Crie um mecanismo para a classe GarotoZumbi
que lhe permita acesso aos atributos. Deve ser possível:
idade
(mas não modificá-lo);nome
.Consultar não significa mostrar o atributo no console, significa que um programa externo ou outro objeto devem ser capazes de ter acesso ao valor do atributo. O programa externo ou objeto decidem o que fazer com o valor.
O mecanismo que você vai criar tem que manter todos os atributos como private
.
Para este e os próximos exercícios que solicitarem modificação na classe, você deve copiar o códgo da classe que vai mudá-lo na célula destino e acrescentar ou modificar o que quiser.
Métodos get
e set
são usadas para expor os atributos indiretamente. Esta exposição é chamada de propriedade.
get
(leitura da propriedade) -> get seguido do nome do atributo - retorna o valor;public int getIdade() {
return idade;
}
public String getNome() {
return nome;
}
set
(modificação da propriedade) -> set seguido do nome do atributo - recebe argumento com novo valor.public void setNome(String nome) {
this.nome = nome;
}
Para propriedades somente de leitura o método set
não é definido.
In [4]:
public class GarotoZumbi
{
private int idade;
private String estado;
private String nome;
public GarotoZumbi(int idade, String estado, String nome) {
this.idade = idade;
this.estado = estado;
this.nome = nome;
}
public int getIdade() {
return idade;
}
public String getNome() {
return nome;
}
public void setNome(String nome) {
this.nome = nome;
}
public void mostra() {
// cabeleira
if (idade >= 2)
System.out.println(" *");
// corpo com olhos
if (estado.equalsIgnoreCase("acordado"))
System.out.println(" o*o");
else
System.out.println(" -*-");
// barba
if (idade >= 3)
System.out.println("*****");
System.out.println(nome);
System.out.println();
}
public void cresce() {
if (idade < 3)
idade++;
mostra();
}
public void acorda() {
estado = "acordado";
mostra();
}
public void dorme() {
estado = "dormindo";
mostra();
}
}
GarotoZumbi garoto = new GarotoZumbi(1, "acordado", "Asdrubal");
garoto.cresce();
System.out.println("Nome do Zumbi: " + garoto.getNome());
System.out.println("Idade do Zumbi: " + garoto.getIdade());
garoto.setNome("Quincas");
System.out.println("Novo nome: " + garoto.getNome());
É possível se criar mais de um método com o mesmo nome para uma classe, entretanto cada um dos métodos tem que ter uma assinatura diferente. A assinatura é definida pela sequência de tipos dos parâmetros (independentemente do nome desses parâmetros).
Por exemplo, considere que eu quero criar duas versões para o método cresce
. A primeira versão é igual a já existente cresce()
sem parâmetros; a segunda recebe como parâmetro quantos anos eu quero que o Garoto Zumbi cresça: cresce(int anos)
. Estas duas assinaturas são consideradas diferentes:
cresce()
- sem parâmetroscresce(int anos)
- com um parâmetro inteiroPara cada uma das assinaturas você pode criar uma implementação diferente:
public void cresce() {
if (idade < 5)
idade++;
mostra();
}
public void cresce(int anos) {
if (idade + anos <= 3)
idade += anos;
mostra();
}
Criar dois métodos como mesmo nome e assinaturas diferentes se chama sobrecarga de métodos. O Java saberá quem chamar de acordo com o tipo dos parâmetros (se chamar sem parâmetros aciona o primeiro e com um inteiro como parâmetro aciona o segundo).
Note que o nome do parâmetro nunca importa na assinatura, somente o tipo. Portanto, você não pode criar duas assinaturas assim:
cresce(int anos)
- com um parâmetro inteirocresce(int meses)
- com um parâmetro inteiroMesmo tendo nomes diferentes eles têm o mesmo tipo, portanto são a mesma assinatura e o Java não aceitará.
In [ ]:
public class GarotoZumbi
{
private int idade;
private String estado;
private String nome;
public GarotoZumbi(int idade, String estado, String nome) {
this.idade = idade;
this.estado = estado;
this.nome = nome;
}
public void mostra() {
// cabeleira
if (idade >= 2)
System.out.println(" *");
// corpo com olhos
if (estado.equalsIgnoreCase("acordado"))
System.out.println(" o*o");
else
System.out.println(" -*-");
// barba
if (idade >= 3)
System.out.println("*****");
// calcas
if (idade >= 4)
System.out.println("#####");
// pernas
if (idade >= 5)
System.out.println("/ \\");
System.out.println(nome);
System.out.println();
}
public void cresce() {
if (idade < 5)
idade++;
mostra();
}
public void cresce(int anos) {
if (idade + anos <= 3)
idade += anos;
mostra();
}
public void acorda() {
estado = "acordado";
mostra();
}
public void dorme() {
estado = "dormindo";
mostra();
}
}
GarotoZumbi garoto = new GarotoZumbi(1, "acordado", "Asdrubal");
garoto.mostra();
garoto.cresce(2);
garoto.cresce();
In [ ]:
public class GarotoZumbi
{
private int idade;
private String estado;
private String nome;
public GarotoZumbi(int idade, String estado, String nome) {
this.idade = idade;
this.estado = estado;
this.nome = nome;
}
public void mostra() {
// cabeleira
if (idade >= 2)
System.out.println(" *");
// corpo com olhos
if (estado.equalsIgnoreCase("acordado"))
System.out.println(" o*o");
else
System.out.println(" -*-");
// barba
if (idade >= 3)
System.out.println("*****");
// calcas
if (idade >= 4)
System.out.println("#####");
// pernas
if (idade >= 5)
System.out.println("/ \\");
System.out.println(nome);
System.out.println();
}
public void cresce() {
cresce(1);
}
public void cresce(int anos) {
if (idade + anos <= 3)
idade += anos;
mostra();
}
public void acorda() {
estado = "acordado";
mostra();
}
public void dorme() {
estado = "dormindo";
mostra();
}
}
GarotoZumbi garoto = new GarotoZumbi(1, "acordado", "Asdrubal");
garoto.mostra();
garoto.cresce(2);
garoto.cresce();
In [4]:
class Emprestimo {
private float s;
private int n;
private float j;
private int corrente;
private float p;
public Emprestimo(float s, int n, float j) {
this.s = s;
this.n = n;
this.j = j;
corrente = 1;
this.p = s;
}
public float proximaParcela() {
float retorno = p;
corrente++;
if (corrente <= n)
p = p + (p * (j/100));
else
p = 0;
return retorno;
}
}
// codigo principal
Emprestimo emprestimo1 = new Emprestimo(200, 5, 1),
emprestimo2 = new Emprestimo(500, 7, 2);
int i = 1;
float p1 = emprestimo1.proximaParcela();
float p2 = emprestimo2.proximaParcela();
while (p1 > 0 || p2 > 0) {
if (p1 > 0)
System.out.println("Emprestimo 1: parcela " + i + " eh " + p1);
if (p2 > 0)
System.out.println("Emprestimo 2: parcela " + i + " eh " + p2);
p1 = emprestimo1.proximaParcela();
p2 = emprestimo2.proximaParcela();
i++;
}
Modifique a classe empréstimo acrescentando dois métodos chamados parcela
com sobrecarga. Eles devem se comportar da seguinte maneira:
parcela
sem informar a parcela - retorna o valor da parcela corrente (sem deslocar a parcela corrente para a próxima parcela);parcela
informando o número da parcela - retorna o cálculo da parcela informada (retorna zero se a parcela informada não existir).Ambos os métodos são apenas de consulta, portanto, eles não modificam a parcela corrente que continuará a mesma.
Na execução, ambos os métodos foram usados em paralelo para testes. Os números de ponto flutuante podem apresentar problemas de precisão, como será discutido em sala.
In [15]:
import java.lang.Math;
class Emprestimo {
private float s;
private int n;
private float j;
private int corrente;
private float p,
proxima;
public Emprestimo(float s, int n, float j) {
this.s = s;
this.n = n;
this.j = j;
corrente = 1;
this.p = -1; // antes da primeira parcela
this.proxima = s;
}
public float proximaParcela() {
p = proxima;
corrente++;
if (corrente <= n)
proxima += (proxima * (j/100));
else
proxima = 0;
return p;
}
public float parcela() {
return p;
}
public float parcela(int numero) {
float resultado = 0;
if (numero <= n)
resultado = s * (float)Math.pow(1 + j/100, numero-1);
return resultado;
}
}
// codigo principal
Emprestimo emprestimo1 = new Emprestimo(200, 5, 1),
emprestimo2 = new Emprestimo(500, 7, 2);
int i = 1;
emprestimo1.proximaParcela();
emprestimo2.proximaParcela();
while (emprestimo1.parcela() > 0 || emprestimo2.parcela() > 0) {
if (emprestimo1.parcela() > 0) {
System.out.println("Emprestimo 1: parcela " + i + " eh " + emprestimo1.parcela());
System.out.println(" parcela " + i + " eh " + emprestimo1.parcela(i));
}
if (emprestimo2.parcela() > 0) {
System.out.println("Emprestimo 2: parcela " + i + " eh " + emprestimo2.parcela());
System.out.println(" parcela " + i + " eh " + emprestimo2.parcela(i));
}
emprestimo1.proximaParcela();
emprestimo2.proximaParcela();
i++;
}