Overloading Made Hard—Method Matching

6 respostas
faelcavalcanti

Fala pessoal. Estou com uma dúvida danada quanto ao uso do overload em conjugado com as situações: [widening], [Autoboxing] e [Var-args].

Porém, estive revisando o livro de kathy sierra, voltado para o exame (310-055) e peguei o seguinte exemplo:
class Vararg {
	static void wide_vararg(long... x) { System.out.println("long..."); }
	static void box_vararg(Integer... x) { System.out.println("Integer..."); }

	public static void main(String [] args) {
		wide_vararg(5,5); // needs to widen and use var-args
		box_vararg(5,5); // needs to box and use var-args
	}
}
Em que ele executa sem problemas a saída, em que até aí não é surpresa nenhuma:
long... Integer...
Como o assunto tratado é sobre overload, a idéia seria manter o mesmo nome do método modificando a sua assinatura, no caso a lista de argumentos, justificando corretamente o seu uso. Visando isto, efetuei algumas mudanças no código acima, para que tenha-se o mesmo nome do método e não diferente. Vejam abaixo:
class Vararg {
	static void box_vararg(long... x) { System.out.println("long..."); }
	static void box_vararg(Integer... x) { System.out.println("Integer..."); }

	public static void main(String [] args) {
		long a = 3;
		long b = 2;
		
		Integer x = 2;
		Integer y = 8;
		
		box_vararg(a,b); // needs to widen and use var-args
		box_vararg(x, y); // needs to box and use var-args
	}	
}
O problema está na linha:
box_vararg(x, y); // needs to box and use var-args
em que o compilador alegremente me informa:
The method box_vararg(long[]) is ambiguous for the type Vararg
Segue abaixo as especificações quanto ao uso do overload avançado, retirados diretamente do livro:
As we can see, you can successfully combine var-args with either widening or boxing. Here's a review of the rules for overloading methods using widening, boxing, and var-args:

* Primitive widening uses the "smallest" method argument possible.
* Used individually, boxing and var-args are compatible with overloading.
* You CANNOT widen from one wrapper type to another. (IS-A fails.)
* You CANNOT widen and then box. (An int can't become a Long.)
* You can box and then widen. (An int can become an Object, via Integer.)
* You can combine var-args with either widening or boxing.


Minha preocupação agora seria com as questões do tipo drag-and-drop, em que é quase certa uma coisa típica destas, mas talvez eles abordem juntamente com o uso de generics, sei lá!

Contudo minha dúvida, a princípio baseia-se em como tentar efetuar a compilação e execução do meu código modificado.

6 Respostas

brunohansen

XXXXXXXXXXXXXXX Post Sensurado so falei merda XXXXXXXXXXXXXXXXXX

faelcavalcanti

Pode ser merda para você, o que implica também que pode ser uma dúvida de uma outra pessoa e que é um dos tópicos a se ter mais cuidado.

faelcavalcanti

Não entendi bem ao certo qual seria o problema, mas aparentemente a questão do uso do widening, é para que não haja a necessidade de se ter que criar outro método, já que o overload ocorre em tempo de compilação. O mesmo pode acontecer utilizando-se objetos, desde que estejam na mesma “árvore de herança”.

A prioridade para que a máquina virtual identifique qual o método que será executado será pelo uso de widening, autoboxing e posteriormente o uso de var-args.

O que dificultou um pouco também foi quanto ao uso com generics, pois agora temos diversas técnicas e cuidados a termos na prova em questões de sintaxe e execução quanto ao uso do override e overload.

Que venham as questões de drag-and-drop, teríamos que levantar uma estimativa de tempo para cada questão deste tipo.

rodrigo_lm

faelcavalcanti achei seu topico bem interessante… até agora não entendi pq da erro de compilação… alguem poderia ajudar ???

faelcavalcanti

Efetuei outra classe com mais alguns métodos, como abaixo:

package teste;

class BoxOrVararg {
	
	static void go(long ... y) { System.out.println("long ..."); }
	static void go(Long ... y) { System.out.println("Long ..."); }
	static void go(Integer ... y) { System.out.println("Integer ..."); }
	
	public static void main(String [] args) {

		go(5, 5);
		
	}	
}

Notem que ocorre o mesmo problema:

The method go(long[]) is ambiguous for the type BoxOrVararg

Estive fazendo uma re-leitura sobre o assunto, e como no Java 5 agora existem 3 novas formas avançadas de overloading que devem ser esclarecidas como mencionei acima:

Widening
Autoboxing
Var-args

E você pode ter o uso de widening juntamente com:

Widening beats boxing Widening beats var-args

A ambiguidade que está ocorrendo é justamente dentro dos dois métodos abaixo:

static void go(Long ... y) { System.out.println("Long ..."); }
static void go(Integer ... y) { System.out.println("Integer ..."); }

Caso eu comente alguns deles o código irá compilar e rodar normalmente.

E a conclusão e aprendizado que tive é de que ocorrerá ambiguidade quando o valor passado para a chamada do método for ambiguo(menciono ambiguo por conta que quebrei a regra que mencionei acima, You CANNOT widen and then box. ) ao valor esperado, por exemplo, os dois métodos que mencionem acima compilam na minha classe, mas eu deveria usar o bom senso e ter que deixar apenas uma declaração que atendesse a maioria, e deixar total liberdade para os programadores que vinhessem a usar, possibilitando, lógico, estes novos recursos, mesmo sem ter qualquer perda de precisão, e assim eu não precisaria ter que ficar criando métodos para diversas situações de tipos primitivos.

A bronca não está só na chamada do método, mas sim nas assinaturas dos métodos disponíveis para uso.

E para fixar de vez os cuidados quando ao uso, cito novamente as regras, retirado à luz da página 244 do livro de kathy sierra e bert bates, direcionado para o exame(310-055):

* Primitive widening uses the "smallest" method argument possible. * Used individually, boxing and var-args are compatible with overloading. * You CANNOT widen from one wrapper type to another. (IS-A fails.) * You CANNOT widen and then box. (An int can't become a Long.) * You can box and then widen. (An int can become an Object, via Integer.) * You can combine var-args with either widening or boxing.
É bom ter cuidado!

:wink:

faelcavalcanti

Errei quando disse “alguns deles”, era para ter mencionado apenas o método:

Foi mal.

:smiley:

Criado 16 de agosto de 2006
Ultima resposta 22 de ago. de 2006
Respostas 6
Participantes 3