Eu sempre achei que um fosse aplicadas as mesmas regras de subscrição em relação a método com retorno covariante.
eles nada mais são do que métodos subscritos que o retorno pode ser uma subclasse do método declarado na superclasse…
e para acessar um método com retorno covariante aplica-se o mesmo esquema para acessar um método subscrito certo?
entao alguem pode me explicar oq ocorre na questão 10 do whizlabs ( modo certification mode / pratice test 1).
Aproveitando o tópico a questão 7 desse mesmo teste, está errada… concordam comigo?
Talvez eu até saiba… e muita gente também.
Mas não vou me dar ao trabalho de baixar o whizlabs só para ler a questão.
Preguiça é fogo…
Resumindo é o seguinte…
CovariantTest c1= new SubCovariantTest();
System.out.println(c1.getObject().x);
pq qui imprimi o método declarado em CovariantTest e nao o da SubCovariantTest?
método na CovariantTest é esse: public A getObject(){ return new A }
e o método declarado na SubCovariantTest é: public B getObject() { return new B }
sendo que B extend A
e SubCovariant extend Covariant
[quote=gugaa_df]Resumindo é o seguinte…
CovariantTest c1= new SubCovariantTest();
System.out.println(c1.getObject().x);
pq qui imprimi o método declarado em CovariantTest e nao o da SubCovariantTest?
método na CovariantTest é esse: public A getObject(){ return new A }
e o método declarado na SubCovariantTest é: public B getObject() { return new B }
sendo que B extend A
e SubCovariant extend Covariant[/quote]
O problema está nesse x. Somente os métodos são escolhidos em tempo de execução e não os membros de classe entendeu?
Um abraço!
Desculpa mas permaneci sem entender…
Só falta entender isso, vou fazer a prova dia 21 agora, preciso mto aprender isso
bom pq o metodo chamado é o da referencia e nao da execução a referencia que defini qual o metodo vai ser chamado nesse caso… o ele chama o metodo da super classe que tem o mesmo tipo da sua referencia o metodo da subclasse tem o tipo que nao é o mesmo da referencia… . entao antes de executar a subscricao ele sempre vai chamar primeiro o metodo da superclasse e se o metodo foi subscrito com o mesmo tipo ele chama do objeto.
E no caso de variaveis sempre vai chamar o da referencia.
Bom digamos que eu vou aceitar isso, entender eu entendi…
mas entao nao podemos dizer que se aplica as regras de subscrição em cima deles, só dizem que é subscrito pq permanece os mesmo argumentos do método, certo?
mas na hora de acessar os métodos, as regras são as mesmas de acessar um método sobrecarregado. o que importa é o tipo do objeto, e nao o tipo do objeto que está referenciando…
caem mtas dessa na prova?
o que importa é o tipo do objeto e a ordem do args, mais o tipo.
caiu 2 questoes que envolvia retorno covariantes…
gugaa as regras de subscrição valem da mesma maneira… veja o q ta acontecendo…
- não existe essa regra de polimorfismo para os atributos, ou seja, se a classe A (superclasse) tem um atributo x com valor 10 e a classe B (subclasse de A) tem um atributo x com valor 5 e vc faz…
A a = new B();
exibe(a.x);
-
Vai exibir 10, pois vai exibir o valor do atributo da classe A que é o tipo da variável a.
-
As regras de subscrição só existem para os métodos (onde a versão que vai ser executada é a do real objeto instanciado, ao invés da classe da variável).
Então, vamos ao seu caso:
CovariantTest c1= new SubCovariantTest();
System.out.println(c1.getObject().x);
O que está acontecendo?
I. c1 é do tipo CovariantTest e, portanto, em termos de compilação o tipo esperado de getObject é A e, portanto, ele vai sempre buscar o valor do atributo x que está em A.
II. como o objeto real instanciado é do tipo SubCovariantTest, a versão do getObject() que será executada é a dessa classe (ou seja, aplica-se normalmente a regra de subscrição para a chamada do método).
III. porém, como descrito no item I, embora o objeto real retornado seja do tipo B, o tipo do retorno é A e, mesmo tendo um objeto B vai ser exibido o valor do atributo A.
Para entender melhor, o seu código é o mesmo que o seguinte:
CovariantTest c1= new SubCovariantTest();
A a = c1.getObject();
System.out.println(a.x);
Entenda que esse código é o mesmo que o que coloquei na explicação acima:
A a = new B();
exibe(a.x);
Assim, o valor do atributo a ser lido é baseado no tipo da variável e não do tipo do objeto.
Ficou meio extensa a explicação, mas espero que tenha entendido.
[]'s
Acho que entendi, entao quer dizer que se nao tivesse chamando o atributo no final, por exemplo c1.getObject().x se nao tivesse o .x no fim da instrução chamaria o getObject de B?
Ótima explicação, mto obrigado!
espero ter entendido!
Independente de ter chamado o atributo no final, o getObject() chamado foi o de B. Só que para o compilador, o getObject() chamado retorna um objeto do tipo A (por causa do tipo da variável c1, que é CovariantTest). E portanto, ele trata o getObject() retornado como do tipo A e quando vc chama o atributo no final, ele tenta chamar o atributo de A. Por isso, o resultado exibido é o x do tipo A.
Se vc modificar os métodos getObject() para exibir por exemplo “chamou método da superclasse” e “chamou método da subclasse”. Você verá que ele vai exibir essa segunda opção. Porque a subscrição funcionou normalmente.
Na hora de exibir o atributo x, como o tipo de retorno em tempo de compilação é A, ele vai buscar o valor de x na “classe A” e, por isso, exibe tal resultado.