[Resolvido]Exercício - Herança e Polimorfismo

12 respostas
lucas_guj

Fala pessoal, mais um exercício que tive dificuldade em fazer. Tenho um exemplo do livro já feito, utilizando polimorfismo. Não se assustem com o tamanho do código porque não tem nada de complexo ai para vocês veteranos até porque eu sou iniciante e ainda estou no cap 10 do livro. É o seguinte eu tenho uma superclasse abstrata Funcionario na qual as outras classes a estendem - FuncionarioSalariado, FuncionarioHora, FuncionarioComissionado e a classe FuncionarioComissionadoSalarioBase que estende de FuncionarioComissionado e por ultimo a FolhaDePagamentos que é o aplicativo que nao estende ninguém. Cada classe implementa o método abstrato da classe Funcionario para calcular seu salario de acordo com suas propriedades. O problema agora é que eu tenho que usar uma classe Data de um exemplo muito anterior que valida a data exemplo: DD/MM/AAAA. E eu tenho que adicionar 100 reais de bonus no salario do funcionario se o mes de aniversario dele for o mesmo que o mes atual. Peço a ajuda para resolver esse problema, não estou pedindo meu dever de casa. Quem tiver paciência de olhar e me ajudar agradeço.

SUPERCLASSE FUNCIONARIO

// Figura 10.4: Funcionario.java
// Superclasse abstrata Funcionario
import java.util.Calendar;

public abstract class Funcionario
{
	private String primeiroNome;
	private String ultimoNome;
	private String numeroSeguroSocial;
	private Data dataDeAniversario;
	
	// Construtor de cinco argumentos
	public Funcionario( Data data, String primeiro, String ultimo, String nss )
	{
		
		dataDeAniversario 	= data;
		primeiroNome 		= primeiro;
		ultimoNome	 		= ultimo;
		numeroSeguroSocial 	= nss;
	}
	
	// configura o nome
	public void setPrimeiroNome( String primeiro )
	{
		primeiroNome = primeiro; // deve validar
	}
	
	// retorna o nome
	public String getPrimeiroNome()
	{
		return primeiroNome;
	}
	
	// configura o sobrenome
	public void setUltimoNome( String ultimo )
	{
		ultimoNome = ultimo; // deve validar
	}
	
	// retorna o sobrenome
	public String getUltimoNome()
	{
		return ultimoNome;
	}
	
	// configura o CIC
	public void setNSS( String nss )
	{
		numeroSeguroSocial = nss;
	}
	
	// retorna o CIC
	public String getNSS()
	{
		return numeroSeguroSocial;
	}
	
	// retorna a representação String do objeto Funcionario
	@Override // indica que esse método sobrescreve um método de superclasse
	public String toString()
	{
		return String.format( "%s %s\nNúmero de Seguro Social: %s", 
			getPrimeiroNome(), getUltimoNome(), getNSS() );
	}
	
	// método abstract sobrescrito por subclasse concretas
	public abstract double calculaSalario(); // nenhuma implementação aqui
	
	public int adicionalPorAniversario()
	{
		Calendar c = Calendar.getInstance();
		c.setTime(c.getTime());
		
		if( c.get(Calendar.MONTH) + 1 == dataDeAniversario.getMes() )
			return 100;
		
		return 0;
	}
}

CLASSE DATA

// Figura 8.7: Data.java
// Declaração da classe Data

public class Data
{
	private int dia; // 1-31 conforme o mês
	private int mes; // 1-12
	private int ano; // qualquer ano
	
	// construtor: chama checkMes para confirmar o valor adequado para mes;
	// chama checkDia para confirmar o valor adequado para dia
	public Data( int day, int month, int year )
	{
		dia = checkDia( day ); // valida dia
		mes = checkMes( month ); // valida month
		ano = year; // poderia validar ano
	}
	
	// método utilitário para confirmar o valor adequado de dia com base em mes e ano
	private int checkDia( int testaDia )
	{
		int[] diasPorMes = 
			{ 0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
			
		// veririca se dia está no intervalo para mes
		if( testaDia > 0 && testaDia <= diasPorMes[ mes ] )
			return testaDia;
		
		// verifica ano bissexto
		else if( mes == 2 && testaDia == 29 && ( ano % 400 == 0 || ( ano % 4 == 0 && ano % 100 != 0 ) ) )
			return testaDia;
			
		//System.out.printf( "Dia inválido (%d) configura para 1.", testaDia );
		return testaDia; // mantém o objeto em estado consistente
	}
	
	// método utilitário para confirmar o valor adequado do mes
	public int checkMes( int testaMes )
	{
		if( testaMes > 0 && testaMes <= 12 ) // valida mes
			return testaMes;
		else
		{
			System.out.printf(
				"Mês inválido (%d) configure para 1.", testaMes );
			return 1; // mantém o objeto em estado consistente
		}
	}
	
	public int getMes()
	{
		return mes;
	}
	
	// retorna um String no formato mês/dia/ano
	public String toString()
	{
		return String.format( "%d/%d/%d", dia, mes, ano );
	}	
}

CLASSE FUNCIONARIO SALARIADO

// Figura 10.5: FuncionarioSalariado.java
// A classe concreta FuncionarioSalariado estende a classe abstrata Funcionario

public class FuncionarioSalariado extends Funcionario
{
	private double salarioSemanal;
	private Data dataS;
	
	// construtor com quatro argumentos
	public FuncionarioSalariado(Data data, String primeiro, String ultimo, String nss, double salarioS )
	{
		super( data, primeiro, ultimo, nss ); // passa para o construtor de Funcionário
		setSalarioSemanal( salarioS ); // valida e armazena o salário
	}
	
	// configura o salário
	public void setSalarioSemanal( double salarioS )
	{
		salarioSemanal = salarioS < 0.0 ? 0.0 : salarioS;
	}
	
	// retorna o salário
	public double getSalarioSemanal()
	{
		return salarioSemanal;
	}
	
	// calcula os rendimentos; sobrescreve o método calculaSalario em Funcionario
	@Override
	public double calculaSalario()
	{
		return salarioSemanal;
	}
	
	// retorna a representação String do objeto FuncionarioSalariado
	@Override
	public String toString()
	{
		return String.format( "Funcionário salariado: %s\n%s: $%,.2f",
			super.toString(), "Salário semanal", getSalarioSemanal() );
	}
}

CLASSE FUNCIONARIO HORA

// Figura 10.6: FuncionarioHora.java
// Classe FuncionarioHora estende Funcionario.

public class FuncionarioHora extends Funcionario
{
	private double salarioHora; // salário por hora
	private double horas; // horas trabalhadas durante a semana
	private Data dataH;
	
	// construtor de cinco argumentos
	public FuncionarioHora( Data data, String nome, String sobrenome, String nss, double salarioH, double horasT )
	{
		super( data, nome, sobrenome, nss );
		setSalarioHora( salarioH ); // valida a remuneração por hora
		setHoras( horasT );// valida as horas trabalhadas
	}
	
	// configura a remuneração
	public void setSalarioHora( double salarioH )
	{
		salarioHora = ( salarioH < 0.0 ) ? 0.0 : salarioH;
	}
	
	// retorna a remuneração
	public double getSalarioHora()
	{
		return salarioHora;
	}
	
	// configura as horas trabalhadas
	public void setHoras( double horasT )
	{
		horas = ( ( horasT >= 0.0 ) && ( horasT <= 168.0 ) ) ? horasT : 0.0;
	}
	
	// retorna as horas trabalhadas
	public double getHoras()
	{
		return horas;
	}
	
	// calcula os rendimentos; sobrescreve o método calculaSalario em Funcionario
	@Override
	public double calculaSalario()
	{
		if( getHoras() <= 40 ) // nenhuma hora extra
			return getSalarioHora() * getHoras();
		else
			return 40 * getSalarioHora() + ( getHoras() - 40 ) * getSalarioHora() * 1.5;
	}
	
	// retorna a representação de String do objeto FuncionarioHora
	@Override
	public String toString()
	{
		return String.format( "Funcionário hora: %s\n%s: $%,.2f; %s: %,.2f",
			super.toString(), "Salário hora", getSalarioHora(),
			"Horas trabalhadas", getHoras() );
	}
}

CLASSE FUNCIONARIO COMISSIONADO

// Figura 10.7: FuncionarioComissionado.java
// Classe FuncionarioComissionado estende Funcionario.

public class FuncionarioComissionado extends Funcionario
{
	private double vendasBrutas; // vendas brutas semanais
	private double taxaComissao; // porcentagem da comissão
	private Data dataC;
	
	// construtor de cinco argumentos
	public FuncionarioComissionado( Data data, String nome, String sobrenome, String nss, double vendasB, double taxaC )
	{
		super( data, nome, sobrenome, nss );
		setVendasBrutas( vendasB );
		setTaxaComissao( taxaC );
	}
	
	public void setTaxaComissao( double taxa )
	{
		taxaComissao = ( taxa > 0.0 && taxa < 1.0 ) ? taxa : 0.0;
	}
	
	public double getTaxaComissao()
	{
		return taxaComissao;
	}
	
	public void setVendasBrutas( double vendas )
	{
		vendasBrutas = ( vendas < 0.0 ) ? 0.0 : vendas;
	}
	
	public double getVendasBrutas()
	{
		return vendasBrutas;
	}
	
	@Override
	public double calculaSalario()
	{
		return getTaxaComissao() * getVendasBrutas();
	}
	
	@Override
	public String toString()
	{
		return String.format( "%s: %s\n%s $%,.2f; %s: %.2f",
		"Funcionário Comissionado", super.toString(),
		"Vendas brutas", getVendasBrutas(),
		"Taxa de comissão", getTaxaComissao() );
	}
}

CLASSE FUNCIONARIO COMISSIONADO SALARIO BASE

// Figura 10.8: FuncionarioComissionadoSB.java
// Classe FuncionarioComissionadoSB estende a FuncionarioComissionado.

public class FuncionarioComissionadoSB extends FuncionarioComissionado
{
	private double salarioBase; // salário base por semana
	private Data dataCS;
	
	// construtor de seis argumentos
	public FuncionarioComissionadoSB( Data data, String nome, String sobrenome, 
		String nss, double vendas, double taxa, double salario )
	{
		super( data, nome, sobrenome, nss, vendas, taxa );
		setSalarioBase( salario );
	}
	
	public void setSalarioBase( double salario )
	{
		salarioBase = ( salario < 0.0 ) ? 0.0 : salario;
	}
	
	public double getSalarioBase()
	{
		return salarioBase;
	}
	
	@Override
	public double calculaSalario()
	{
		return  getSalarioBase() + super.calculaSalario();
	}
	
	@Override
	public String toString()
	{
		return String.format( "%s %s; %s: $%,.2f",
			"Base de assalariado", super.toString(),
			"Salário Base", getSalarioBase() );
	}
}

CLASSE FOLHA DE PAGAMENTOS

// Figura 10.9: FolhaDePagamentosTeste.java
// Programa de teste da hierarquia Funcionario

public class FolhaDePagamentosTeste
{
	public static void main( String[] args )
	{		
		Data dataFS   = new Data( 07, 01, 1994 );
		Data dataFH   = new Data( 10, 02, 2000 );
		Data dataFC   = new Data( 16, 03, 2005 );
		Data dataFCSB = new Data( 02, 04, 1990 );
		
		// cria objetos de sublclasse
		FuncionarioSalariado funcionarioS = new FuncionarioSalariado(
			dataFS , "Lucas", "Santos", "111-11-1111", 800.00 );
		FuncionarioHora funcionarioH = new FuncionarioHora(
			dataFH, "Thyago", "Santos", "222-22-2222", 16.745, 40 );
		FuncionarioComissionado funcionarioC = new FuncionarioComissionado(
			dataFC, "Mauricio", "Cordeiro", "333-33-3333", 10.000, .06 );
		FuncionarioComissionadoSB funcionarioCSB = new FuncionarioComissionadoSB(
			dataFCSB, "Marina", "Meireles", "444-44-4444", 5.000, .04, 300 );
		
		// cria um array funcionario de 4 elementos
		Funcionario[] funcionarios = new Funcionario[4];
		
		// inicializa o array com funcionários
		funcionarios[0] = funcionarioS;
		funcionarios[1] = funcionarioH;
		funcionarios[2] = funcionarioC;
		funcionarios[3] = funcionarioCSB;
		
		System.out.println( "Funcionários processados polimorficamente:\n" );
		
		// processa genericamente cada elemento no array funcionários
		for( Funcionario funcionarioAtual : funcionarios )
		{
			System.out.println( funcionarioAtual ); // invoca toString
			// determina se elemento é um Funcionario Comissionado com Salario Base
			if( funcionarioAtual instanceof FuncionarioComissionadoSB )
			{
				// downcast da referência de Funcionário para
				// referência a FuncionárioCSB
				FuncionarioComissionadoSB funcionario = ( FuncionarioComissionadoSB ) funcionarioAtual;
				
				funcionario.setSalarioBase( 1.10 * funcionario.getSalarioBase() );
				
				System.out.printf(
					"Novo salário base com 10%% de aumento é: $%,.2f\n",
					funcionario.getSalarioBase() + funcionario.adicionalPorAniversario() );
			}
			
			System.out.printf( 
				"Ganhou $%,.2f\n\n", funcionarioAtual.calculaSalario() + funcionarioAtual.adicionalPorAniversario() );
		}
		
		// obtém o nome do tipo de cada objeto no array funcionarios
		for( int j = 0; j < funcionarios.length; j++ )
			System.out.printf( "Funcionários %d é um %s\n", j, funcionarios[ j ].getClass().getName() );
	}
}

12 Respostas

ViniGodoy

Por favor, ao postar tópicos, não coloque em destaque informações óbvias como [Dúvida], [Ajuda] ou [Socorro]. Use as tags informativas para coisas importantes, como [Resolvido].

lucas_guj

Pior que tava sem a tag e eu pensei que era para colocar porque senao poderiam pensar que fosse alguma outra coisa sem ser duvida como já vi aqui alguns tópicos quando na verdade eram aplicativos. Desculpa. Vlw pelo aviso

ribclauport

Bom ja que a classe Funcionáro tem um método chamado calcular salário, que na minha opnião, quebra a coesão acrescente outro desta forma:

public int adicinonalPorAniverssario() {

		Calendar c = Calendar.getInstance();
		c.setTime(c.getTime());

		if (c.get(Calendar.MONTH) + 1 == dataDeAniversario.getMes()) {
			return 100; //pode ser alterado para uma constante no código.
		}
		return 0;
	}

E altere as outras classes para receber um objeto Data no construtor.
depois chame este método que irá retornar ou zero ou 100, dependendo do mês.

lucas_guj

Como assim quebra a coesao acrescente? O que é isso? Ainda não conheço essa classe Calendar vou dar uma pesquisada sobre ela e vou utilizar seu metodo e tentar fazer aqui se eu conseguir ou não respondo assim que acabar. Obrigado pela ajuda

lucas_guj

ribclauport muito obrigado pela ajuda. Eu editei meu primeiro post, fazendo as modificações que você falou para fazer, e por enquanto deu certo. Mais tem um PORÉM. As datas que eu passo para o funcionario não são validadas, ou seja, se eu colocar uma data errada ele não vai saber, porque não é passado nenhuma data para o construtor da classe DATA. Tem como eu chamar um construtor dentro de outro construtor de duas classes não relacionadas por herança? Dei uma lida na java API sobre a classe Calendar pois nunca a utilizei, e me responde se eu entendi ou estou errado.

[b]A classe Calendar é uma classe abstrata por isso não posso instancia-la

então eu crio uma variável de referência c e chamo o método static dela getInstance() que retorna a data e hora e tudo relacionado ao calendario ATUAL[/b]

Calendar c = Calendar.getInstance();

Aí eu vou pega a referencia e acesso o método setTime( Date date ) que tem como um parâmetro um objeto do tipo data e passo o meu objeto Date que retorna o valor deste calendario de tempo. Ou seja:

c.getTime(); // Retorna um objeto Date com o valor de tempo do calendário
c.setTime(Date date); //Define o tempo do calendário com a data determinada

Aí você fez isso

c.setTime(c.getTime());

Para saber se o mês atual é o mês em que o funcionário faz aniversário você fez uma verificação. O método:

c.get(); // retorna o valor de campo do calendário

E a classe Calendar tem constantes que indicam DIA(Day) ou (DAY_OF_MONTH), Mes(MONTH) etc.
Então como é uma constante estática eu acesso e passo como parâmetro do método get().

c.setTime( c.getTime() );

E acrescento mais um ao mês retornado porque o mês de Janeiro na classe Calendar é o valor 0 então eu comparo com o meu mês que é 1.

if( c.get(Calendar.MONTH) + 1 == dataDeAniversario.getMes() )
			return 100;

return 0;

E agora? O que eu falei sobre a classe Calendar está certo ou errei em algo?

ribclauport

Sim, esta certo sobre calendar,
agora tem como você me explicar melhor o que quer fazer ae dae eu dou uma força…
aguardo.

lucas_guj

Eu quero arranjar um jeito de relacionar a classe funcionária com a classe data . Embora a classe funcionária tem uma relação " tem um " com a classe data , eu não passo nada para o construtor da classe data , ou seja , quando eu boto qualquer data ela não é validada no construtor da classe data , então eu posso colocar uma data errada tipo dia 32 que minha classe não vai saber que estar errada .

Então o que eu quero é dar um jeito de passar o objeto data para o construtor da classe data antes de armazená-lo

Obrigado pela ajuda .

ribclauport

Bom não tem la no seu construtor isso aqui…

public Data( int day, int month, int year )  
        {  
            dia = checkDia( day ); // valida dia  
            mes = checkMes( month ); // valida month  
            ano = year; // poderia validar ano  
        }

então desta forma está validando a criação certo?

tente colocar o código que você está tentando executar e tal…
por que pelo que entendi a data está sendo validada ae…

lucas_guj

Era para ser validado ai, só que eu não passo nada para o construtor. Não entendi o que você falou .

ribclauport

Bom, se eu entendi você vai ter que criar uma data certo?

vai fazer

new Data(2,7,2012);

desta forma dentro do construtor os metodos de validação estão sendo chamados…
como não ta passando nada para o construtor?

posta ae como ta criando os objetos…

lucas_guj

Eu ja postei todas as minhas classes no primeiro post. Eu crio os objetos Data na classe main FolhaDePagamentos.java. Olha lá na última classe

public class FolhaDePagamentosTeste  
{  
    public static void main( String[] args )  
    {         
        Data dataFS   = new Data( 07, 01, 1994 );  
        Data dataFH   = new Data( 10, 02, 2000 );  
        Data dataFC   = new Data( 16, 03, 2005 );  
        Data dataFCSB = new Data( 02, 04, 1990 );  
          
        // cria objetos de sublclasse  
        FuncionarioSalariado funcionarioS = new FuncionarioSalariado(  
            dataFS , "Lucas", "Santos", "111-11-1111", 800.00 );  
        FuncionarioHora funcionarioH = new FuncionarioHora(  
            dataFH, "Thyago", "Santos", "222-22-2222", 16.745, 40 );  
        FuncionarioComissionado funcionarioC = new FuncionarioComissionado(  
            dataFC, "Mauricio", "Cordeiro", "333-33-3333", 10.000, .06 );  
        FuncionarioComissionadoSB funcionarioCSB = new FuncionarioComissionadoSB(  
            dataFCSB, "Marina", "Meireles", "444-44-4444", 5.000, .04, 300 );  
          
        // cria um array funcionario de 4 elementos  
        Funcionario[] funcionarios = new Funcionario[4];  
          
        // inicializa o array com funcionários  
        funcionarios[0] = funcionarioS;  
        funcionarios[1] = funcionarioH;  
        funcionarios[2] = funcionarioC;  
        funcionarios[3] = funcionarioCSB;

Obrigado pela paciência

lucas_guj

COMO EU SOU LERDO AS VEZES…Eu ja conclui a muito tempo desde que entendi sobre a classe calendar. Preste atenção

Data dataFS   = new Data( 07, 01, 1994 );
Data dataFH   = new Data( 10, 02, 2000 );
Data dataFC   = new Data( 16, 03, 2005 );
Data dataFCSB = new Data( 02, 04, 1990 );

Aqui é o começo do aplicativo FolhaDePagamentos e eu instancio o objeto Data passando os dados para o construtor e validando ¬¬ Eu tava olhando para a classe funcionario pensando que eu teria que passar la devivo a composição mais na verdade a composição lá só serve para cada funcionário ter uma data especifica. OMG

Muito Obrigado ribclauport, me ajudou muito. Tópico Resolvido

Criado 22 de janeiro de 2012
Ultima resposta 24 de jan. de 2012
Respostas 12
Participantes 3