Eu queria tirar uma dúvida com relação ao upcasting e downcasting.
package core.java.volume.um.polimorfismo;
public class Empregado {
public String nome;
public int salario;
public Empregado(String nome, int salario){
this.nome = nome;
this.salario = salario;
}
public String getNome(){
return "";
}
public int getSalario(){
return 1;
}
}
package core.java.volume.um.polimorfismo;
import java.util.ArrayList;
import java.util.List;
public class Gerente extends Empregado {
List<Empregado> lista;
public Gerente(String nome, int salario){
super(nome, salario);
lista = new ArrayList<Empregado>();
lista.add(this);
lista.add(new Empregado("Carlos", 1000));
lista.add(new Empregado("Maria", 500));
Empregado e1 = lista.get(0);
Gerente g1 = (Gerente)lista.get(0);
Gerente g2 = (Gerente)lista.get(1);
}
public void metodoNovo(){
//faça algo
}
}
(1) Na linha 21, uma variável do tipo Empregado recebe uma referência para Gerente. Nesse caso, ocorre um downcasting implícito. Só acesso os métodos que são herdados em Gerente.
(2) Na linha 23, uma variável do tipo Gerente recebe uma referência para um objeto Gerente. Porém, ArrayList é do tipo Empregado. Então, é retornado um objeto Empregado, que aponta para Gerente. Para compatibilização, faço um upcasting explícito. Agora, acesso os métodos novos presentes em Gerente.
(3) Na linha 25, uma variável do tipo Gerente recebe uma referência para um objeto Empregado (pois ArrayList é do tipo Empregado) que referencia um objeto Gerente. Como g2 está recebendo um Empregado, devo fazer um upcasting explícito.
Erro na linha 25! Você não pode atribuir um empregado a gerente! Um empregado não é um gerente, mas um gerente é um empregado então a atribuição funciona nas linhas 21 e 23!
Na linha 21 não existe cast, pois a lista ja é do tipo Empregados! Já quando você adiciona na lista o gerente (linha 16) ocorre um upcasting.
na linha 23 ocorre o contrário, um dowcast, pois você está convertendo um empregado para um gerente!
[quote=x@ndy]Na linha 21 não existe cast, pois a lista ja é do tipo Empregados! Já quando você adiciona na lista o gerente (linha 16) ocorre um upcasting.
na linha 23 ocorre o contrário, um dowcast, pois você está convertendo um empregado para um gerente![/quote]
Eu não estou entendendo. De acordo com Deitel, eu poderia fazer:
Subclasse sub = (Subclasse)new Superclasse();
sub.metodoEspecificoSubclasse();
Li até na 9º versão do livro dele. Em momento de compilação, sem erro. Aparece apenas em tempo de execução.
Deitel fala que:“Java permite a atribuição da referência de uma superclasse a uma variável de subclasse se fizermos uma coerção explícita na referência de superclasse para o tipo de subclasse (…). Se um programa precisar realizar uma operação específica na subclasse em um objeto de subclasse referenciado por uma variável de superclasse, o programa deverá primeiro fazer uma coerção [cast] da referência de superclasse para uma referência de subclasse por meio de uma técnica denominada downcasting.”
O que Deitel faz em seu livro gera ClassCastException para mim.
A palavra chave ai é atribuição você esta atribuindo um sub objeto utilizando uma referencia para um super objeto. Mas o que é essa referencia? É uma instancia do sub objeto!
Utilizando seu exemplo:
[quote=ECO2004]
Subclasse sub = (Subclasse)[b]new Superclasse();[/b]
sub.metodoEspecificoSubclasse();
[/quote]
A primeira coisa que o java faz é instanciar a super classe! Logo em seguida ele vai fazer o cast, mas o que você tem é um super objeto e não um sub e nesse caso o cast falha, pois ele vai antes de atribuir verificar se os Tipos são compativeis ou seja, se é um super objeto ou se o super objeto herda dele o que não ocorre!
O que ele quis dizer que você pode fazer é atribuir uma refencia do super objeto ao sub, mas desde que ele o sub seja o proprio objeto ou herde de do objeto que foi atribuido ao super!
Em herança você tem uma verticalidade, da classe mais abaixo na hierarquia até a mais alta. você pode atribuir a classe mais alta da hierarquia qualquer classe dessa hierarquia, mas não pode atribuir uma referencia de uma classe mais alta a uma mais baixa!
PS: Observe que no seu código ele utiliza a palavra chave instaceof, para verificar se é um objeto é uma instancia de outro ou seja, ou seja, se eles estão dentro da mesma hierarquia
Bem, você disse que o cast falha, mas ele não falha, pelo menos não no livro. Quando estava programando, criei uma Superclasse e uma Subclasse. Quando atribuí uma referência da superclasse ao objeto da subclasse, utilizando um cast como no primeiro exemplo, não houve erro em tempo de compilação, mas houve em runtime.
Resumindo: não sei como fazer o programa não lançar uma ClassCastException, como o Deitel fez.
[quote=ECO2004][quote=x@ndy]
O que ele quis dizer que você pode fazer é atribuir uma refencia do super objeto ao sub [ok], mas desde que ele o sub seja o proprio objeto ou herde de do objeto que foi atribuido ao super![não ok]
[/quote]
Não entendi a parte de cima.
Bem, você disse que o cast falha, mas ele não falha, pelo menos não no livro. Quando estava programando, criei uma Superclasse e uma Subclasse. Quando atribuí uma referência da superclasse ao objeto da subclasse, utilizando um cast como no primeiro exemplo, não houve erro em tempo de compilação, mas houve em runtime.
Resumindo: não sei como fazer o programa não lançar uma ClassCastException, como o Deitel fez.[/quote]
Você não analisou o código dele direito. Não falha pq ele está verificando os tipos. Utilizando o seu exemplo você teria que fazer isso:
if (lista.get(1) instanceof Gerente)
Gerente g2 = (Gerente)lista.get(1);
Quando você cria um objeto Gerente ele herda de Empregado então uma referência a um objeto Gerente, pode ser atribuido a uma variável do tipo Gerente e do tipo Empregado ou a um Object, pois todo mundo herda dele. Se você atribuir um objeto gerente a uma variável do tipo Empregado isso é chamado o upcasting e é ele é implicito, você nem sabe que está acontecendo!
Quando você cria um objeto empregado você não pode atribui-lo ele a uma variavel gerente, pois ele não é um gerente. você criou um empregado e não um gerente. Se você quiser até pode atribuir a uma váriável object, mas nunca ao gerente. Imagine que na construção do Gerente você faz uma série de operações, ou até mesmo que você tenha um construtor diferente o empregado não sabe de nada disso! Ele não sabe como o gerente é então eu não posso converter (cast) um empregado em um gerente. Quando eu estou fazendo um casting, é como se eu estivesse dizendo para o java que que os objetos são do mesmo tipo ele não faz nenhuma operação por fora, ele não cria outro objeto sendo antes de fazer um downcasting eu tenho que verfiicar se eles são do mesmo tipo, ou seja, se meu empregado também é um gerente!
Imagine que você va visitar uma loja. Você vê lá diversos empregados da loja, mas você pede para falar com o gerente e alguem lhe aponte e diga o gerente é aquele lá. É isso o que o downcast está fazendo. Só que caso ele informe errado ao chegar perto você verá o crachá dele então poderá ver que ele não é o gerente.
Pegou?