Boa Noite! apreendi que casting pode ser feito em classes também, a minha dúvida seria qual é a vantagem ou boa prática ou até mesmo obrigatório uso de casting em classes. um exemplo prático me ajudaria bastante. Desde já agradeço!
Boa Noite! apreendi que casting pode ser feito em classes também, a minha dúvida seria qual é a vantagem ou boa prática ou até mesmo obrigatório uso de casting em classes. um exemplo prático me ajudaria bastante. Desde já agradeço!
Ola Ronny, tudo bem ?
Imagine o seguinte cenário. Temos uma classe Funcionário
...
public class Funcionario {
private String nome;
private BigDecimal salario;
// mais código
}
... e temos uma outra classe, Gerente
, que por sua vez é um Funcionário, numa relação de herança ...
public class Gerente extends Funcionario {
private String senha;
// getter e setter para senha
// mais código
}
Quando temos a possibilidade de usar o polimorfismo das referências, seja via herança (como no exemplo), seja por interfaces, podemos ter a seguinte situação.
public class Teste {
public static void main(String[] args) {
Funcionario f = new Funcionario();
Gerente g = new Gerente();
// até aqui tudo normal
Funcionario g2 = new Gerente();
// aqui já temos um exemplo de uso de referencia polimorfica
// em memória temos uma instância de Gerente, porém a partir deste ponto o compilador não sabe disso, visto que armazenamos a referencia de Gerente em uma variavel referencia Funcionario.
}
}
Imagine agora que gostariamos de chamar a partir de g2 o método, digamos setSenha
que recebe uma String.
public class Teste {
public static void main(String[] args) {
//codigo anterior omitido
g2.setSenha("123456");
}
}
Aqui teríamos um erro de compilação. Mas por que? Lembre-se que a JVM em execução sabe que temos uma instancia de gerente em memória, mas em tempo de compilação não temos nada instanciado. O máximo que o compilador sabe sobre g2 é que ela é uma referência do tipo Funcionario
, podendo apontar pra qualquer tipo de funcionario que existir (Funcionario, Gerente ou qualquer outra classe que os estenda). Imagine o que aconteceria se o compilador permitisse que isso passasse. Poderiamos em execução tentar chamar um setSenha(..)
de um possível objeto de Funcionario (somente gerente tem esse metodo definido) armazenado na referencia, causando um erro em runtime.
Como resolver ?
public class Teste {
public static void main(String[] args) {
//codigo anterior omitido
Funcionario g2 = new Gerente();
Gerente gerente2 = (Gerente) g2;
gerente2.setSenha("123456");
}
}
Como sabemos que em g2 possuímos uma referência de gerente podemos pegar essa referência e copiá-la para outra variável, só que dessa vez a variável tem o tipo mais específico Gerente
. Assim o compilador saberá que poderá invocar com segurança tudo aquilo que foi definido na interface dessa mesma classe =)
Mas cuidado! Fazer casting, tanto entre primitivos, como entre referências traz sempre um risco para o código. Entre os primitivos podemos acabar perdendo informação nas cópias entre tipos diferentes. Já entre os referências podemos receber uma chata ClassCastException em runtime nos casos onde tentemos forçar um cast incompatível, por exemplo Gerente xpto = (Gerente) f;
. Neste caso f
guarda uma referencia para um objeto do tipo Funcionario, que não podemos afirmar (com certeza) ser um Gerente (poderia ser um Programador, por exemplo).
Por estes casos dizemos que casting em geral deve ser evitado ao máximo (não é boa prática). A partir do Java 5, a linguagem trouxe o conceito de Generic Types (generics) justamente pra facilitar a vida e evitar os castings que eram feitos sempre nestes casos. -> generics
Espero ter ajudado. Abraço!
Ta indo bem na medido do possível kkkk Muito obrigado! ajudou bastante entendi. Tava com essa dúvida pois sou iniciante em Java e acabo que estou lendo muitas coisas ao mesmo tempo e quero me fundamentar no OO muito bem e praticando boas práticas pois quero ser um Desenvolvedor Java com códigos mais seguros. Agradeço mais um vez Rafael!