Programação Java: Composição: trocando informações entre objetos

Linguagem Java , Programação Java, Java Curso gratis.

  • Composition in Java Exchanging between objects

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.

  • Obtenha seu certificado em programação Java

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

Como citamos em nosso artigo introdutório sobre Classes e Objetos , a comunicação entre seus dados é essencial.
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.

<

table border="0" cellpadding="0" cellspacing="0" style="width: 85%px;">

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)

Vamos descobrir o tempo que o funcionário atrasou convertendo a hora de chegada em segundos.
Simplesmente transformamos a hora em que o funcionário chegou em segundos:
horaChegada.getHour()6060 + 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)

Para o cálculo do tempo trabalhado de um funcionário, vamos levar em conta somente as horas trabalhadas.

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()

Um simples exemplo de get, que retorna a variável ‘tempoTrabalhado’.

Código do nosso programa:

controleHorario.java

public class controleHorario {

public static void main(String[] args) {

Hora horaChegada = new Hora(8, , 1);
Hora horaSaida = new Hora(9, 30, );
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>= && hours 24 )
this.hours = hours;
else
throw new IllegalArgumentException("Hora inválida");

//preenchendo os minutos
if(minutes >= && minutes 60)
this.minutes = minutes;
else
throw new IllegalArgumentException("Minutos inválidos");

//preenchendo os segundos
if( seconds >= && 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 > )
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 )
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…