Ola
Alguém pode me dizer, já que não entendo, o seguinte:
A) quando faço casting de objetos, implícito ou explícito, obtenho exatamente o quê?
B) por que faria casting entre objetos?
Espero que alguém possa me responder (e eu entender).
Obrigado.
Por que se faz casting de objetos?
5 Respostas
Vendo um exemplo com herança fica simples de entender. Imagine que você está modelando uma aplicação que tem as classes Funcionario e Gerente. Um Gerente é um Funcionario e, por isso, Gerente herda de Funcionario. Um gerente tem um bônus de salário, coisa que os outros funcionários não tem. Você implementa isto desta maneira:
public class Funcionario {
private String nome;
private int salario;
public String getNome() {
return this.nome;
}
public int getSalario() {
return this.salario;
}
}
public class Gerente extends Funcionario {
private int bonus;
@Override
public int getSalario() {
return super.getSalario() + this.bonus;
}
public int getBonus() {
return this.bonus;
}
}
Imagine que, em algum momento, você tem uma referência para um objeto Funcionario. Você sabe que ele é um Gerente e precisa saber qual é o bônus de salário. Você NÃO pode fazer isto:
Funcionario funcionario = recebeFuncionarioDeAlgumLugar();
funcionario.getBonus(); // nao funciona, funcionario nao tem bonus, erro de compilação
Então você precisa de um cast:
Funcionario funcionario = recebeFuncionarioDeAlgumLugar();
Gerente gerente = (Gerente) funcionario;
gerente.getBonus(); // isto funciona
Ou seja, você está acessando o mesmo objeto por meio de um tipo diferente. Isto acontece quando você usa interfaces também.
Olá wagnerfrancisco
Obrigado pela ajuda. Vamos analisar o que me passou.
Em relação a pergunta
A) quando faço casting de objetos, implícito ou explícito, obtenho exatamente o quê?
Bom, obtenho um objeto de novo tipo (razão do casting). Esse objeto de novo tipo recebe ou herda (qual dos dois?) do objeto convertido alguma propriedade (é isso?). Já que a subclasse é “maior” que sua superclasse, ou seja contem mais atributos e mais métodos.
No exemplo que deu, ocorreu uma “invasão de corpos” quando se converteu o objeto gerente em funcionário. O “gerente” engravidou “funcionário” com o atributo bônus. Desta forma “funcionário” pode ser tratado pelo programa como “gerente”. Essa seria a base do polimorfismo?
B) por que faria casting entre objetos?
Ainda não entendo para que eu precisaria fazer isso. Como não consigo abstrair, serei literal com o exemplo que deu. Se preciso saber o valor do bônus, não preciso fazer casting de objetos, apenas transfiro o valor para uma variável int bonusG = gerente1.getBonus();, algo assim, para acessar esse valor. O que me faz ficar confuso é o seguinte raciocínio que faço:
Se uma superclasse precisa de um atributo ou funcionalidade de uma subclasse, por que já não construiria essa superclasse com os elementos necessários para obter esses elementos da subclasse?
Ainda sobre casting de objetos, agrego uma nova pergunta:
C) Não há limitação em relação ao “tamanho” dos objetos nos casting descendente (maior para menor)?
Quando fazemos casting descendente (é como chamo) de um int para um byte, temos que fazê-lo de forma explicita para garantir que o Java faça a conversão de espaços, mas isso é dependente de valor, ou seja, se int = 128, a conversão dará um resultado inesperado, pois 128 não cabe em um byte. Esse tipo de limitação de tamanho entre objetos não existe?
Novamente muito obrigado pela sua ajuda.
Abs.
Olá wagnerfranciscoObrigado pela ajuda. Vamos analisar o que me passou.
Em relação a perguntaA) quando faço casting de objetos, implícito ou explícito, obtenho exatamente o quê?
Bom, obtenho um objeto de novo tipo (razão do casting). Esse objeto de novo tipo recebe ou herda (qual dos dois?) do objeto convertido alguma propriedade (é isso?). Já que a subclasse é “maior” que sua superclasse, ou seja contem mais atributos e mais métodos.
No exemplo que deu, ocorreu uma “invasão de corpos” quando se converteu o objeto gerente em funcionário. O “gerente” engravidou “funcionário” com o atributo bônus. Desta forma “funcionário” pode ser tratado pelo programa como “gerente”. Essa seria a base do polimorfismo?
É o mesmo objeto, você apenas enxerga ele de outra maneira (usando outro tipo). Observe que Gerente é um Funcionario, mas tem uma propriedade a mais no exemplo.
No polimorfismo, o comum é evitar estes casts explícitos. Fica mais fácil você enxergar polimorfismo neste exemplo olhando para o método getSalario. É o mesmo método, mas em cada objeto ele se comporta de uma maneira diferente. Para o objeto Funcionario, ele simplesmente retorna o salario. Para o Gerente, ele ainda adiciona um bonus.
Olá wagnerfrancisco
B) por que faria casting entre objetos?Ainda não entendo para que eu precisaria fazer isso. Como não consigo abstrair, serei literal com o exemplo que deu. Se preciso saber o valor do bônus, não preciso fazer casting de objetos, apenas transfiro o valor para uma variável
int bonusG =gerente1.getBonus();, algo assim, para acessar esse valor. O que me faz ficar confuso é o seguinte raciocínio que faço:
Se uma superclasse precisa de um atributo ou funcionalidade de uma subclasse, por que já não construiria essa superclasse com os elementos necessários para obter esses elementos da subclasse?
O ideal realmente é evitar casts explícitos. Mas vou te dar um exemplo onde você usa (não necessariamente é um bom design). Imagine que você tem uma lista com todos os Funcionarios da empresa:
List<Funcionario> funcionarios;
Você quer saber qual é a soma do bonus de todos os gerentes. Neste caso, você não tem como acessar o bonus de cada um sem converter para Gerente. Neste caso você verifica se funcionário é um gerente (instanceof) e faz um cast para gerente, adicionando o bônus.
int bonusTotal = 0;
for each (Funcionario f : funcionarios) {
if (f instanceof Gerente) {
Gerente g = (Gerente) f;
bonusTotal += g.getBonus();
}
}
Mas eu ressalto: o polimorfismo tenta evitar justamente isto. O ideal realmente é ter um design que evite este cast. Em algumas situações, entretanto, isto não é possível.
Você nao bota tudo na superclasse simplesmente por que nem todo Funcionario tem este bonus.
[/quote]
No caso de objetos não. Veja, você só está acessando o mesmo objeto por meio de outra interface, outro tipo.
a) eu tenho um método que recebe um objeto do tipo funcionario, e eu desejo que os que forem Gerentes, tenham métodos diferentes…mais eu gostaria de receber qualquer tipo de funcionario na mesma assinatura de método…, ou se eu quizesse colocar tipos diferentes de objetos em uma mesma lista do tipo funcionario.
daria pra deixar colocar outros tipos:
Supervisor extends Funcionario.
isso é uma base para o polimorfismo…
b) daria pra colocar o método getBonus na classe funcionario, mas todos os funcionarios, quanto gerentes, quanto supervisores teriam esse método… a situação fica pior se tivesse um método mais grave: Contratar() / Aprovar() / Cancelar_Aprovação(), se fosse fazer desta forma eu teria que ter um atributo: int Tipo_Funcionario, e sempre eu teria que verificar o que aquele funcionario é…
O objetivo da Herança é pegar um objeto Generico e especializar tal para funções especificas, reaproveitando o código da super-classe.
C) algumas converções o java não permite, tem que testar pra ver o resultado.
Olás wagnerfrancisco
O segundo exemplo que me deu deixou tudo claro agora. Consegui ver porque fazer.
Obrigado também ao douglaskd, os exemplos que deu complementaram muito bem o do wagnerfrancisco, reforçando o entendimento.
Acredito que essa dúvida desapareceu. Só a prática dirá se ficou claro mesmo.
Vou imprimir este post para usá-lo na ocasião apropriada.
Obrigado. Dúvida resolvida.