Collection

3 respostas
anderline

Pessoal olha só, eu estava tentando fazer a seguinte ação:

Criei uma coleção dessa maneira:

Collection revisores = new HashSet();

Depois instanciei essa classe:

Artigo a = new Artigo();

que tem um método com a seguinte assinatura:

public void setRevisor(Set revisor)

Quando tentei fazer a seguinte ação:

a.setRevisor(revisores);

veio esse erro:

The method setRevisor(Set) in the type Artigo is not applicable for the arguments (Collection)

Tive que resolver fazendo o seguinte:

Ao invés de fazer:

Collection revisores = new HashSet();

eu fiz:

Set revisores = new HashSet();

Aí resolvi ver as assinaturas das classes e vi o seguinte:

HashSet extends AbstractSet implements Set

AbstractSet extends AbstractCollection implements Set

AbstractCollection implements Collection

Fiquei com essa dúvida, se o Collection tá na raiz de tudo, porque não funcionou fazer do jeito q eu tava tentando. Fica essa dúvida.

3 Respostas

faelcavalcanti

Pensando na mesma implementação que você veio seguindo organizei da seguinte forma:

package teste;

import java.util.Collection;
import java.util.HashSet;
import java.util.Set;

public class Artigo {

	Collection<Revisor> revisores;
	
	public void setRevisores(Set<Revisor> revisores) {
		this.revisores = revisores;
	}
	
	public Collection<Revisor> getRevisores() {
		return revisores;
	}
	
	public static void main(String[] args) {

		Artigo artigo = new Artigo();
		
		Collection<Revisor> revisores = new HashSet<Revisor>();
		
		artigo.setRevisores(revisores);
		
	}

}

class Revisor {}
Da forma que se encontra o código, ocorrerá o mesmo problema mencionado.

Você terá total liberdade para declarar a variável revisores, conforme fiz no método main, como abaixo:

Collection revisores = new HashSet();
Mas para atribuir para o método setRevisores, terá que estabelecer o contrato definido pelo método.

Por exemplo, dê uma olhada nesta implementação que fiz agora:

package teste;

import java.util.Set;

interface Animal {}

abstract class Mamifero implements Animal {}
abstract class Reptil implements Animal {}

final class Cachorro extends Mamifero {}
final class Gato extends Mamifero {}

final class Camaleao extends Reptil {}
final class Crocodilo extends Reptil {} 

public class CadeiaAlimentar {
	
	Mamifero animal;
	
	public Animal getAnimal() {
		return animal;
	}
	
	public void setAnimal(Mamifero animal) {
		this.animal = animal;
	}
	
	public static void main(String[] args) {
		
		CadeiaAlimentar cadeia = new CadeiaAlimentar();
		
		Animal cachorro = new Cachorro();		
		
		cadeia.setAnimal(cachorro);		
	}
	
}

Apesar de não utilizar uma implementação de até uma outra subclasse, você poderá ver que o problema é o mesmo.

The method setAnimal(Mamifero) in the type CadeiaAlimentar is not applicable for the arguments (Animal)

Isto consiste por conta do contrato estabelecido pelo método setAnimal, ou seja, como declarei a assinatura do método para Mamifero, acabei restrigindo o tipo de instância que gostaria de receber em meu método setAnimal.

Quando criei a variável cachorro do tipo Animal, acabei quebrando o contrato estabelecido pelo método. Apesar de mamífero implementar a interface animal, não cabe a mim ampliar a restrição estabelecida pelo método.

Ocorre o mesmo no uso de covarância quando tenta-se aplicar o polimorfismo, em que acontece em tempo de runtime, mas isso é só um exemplo. Quanto ao uso de Generics, está perfeito, o problema persiste apenas no contrato do método, pois a intersecção não equivale ao esperado.

Espero ter ajudado. :wink:

faelcavalcanti

Quando mencionei sobre covarância, errei quanto ao que disse que ocorre o mesmo. Na verdade é uma outra situação, mas que aparentemente temos o mesmo problema se não seguirmos o tipo estabelecido ou o que foi definido.

Um exemplo disto seria se um método da superclasse declarasse que levantaria uma exceção do tipo IOException, já na subclasse o mínimo que você poderia fazer seria redeclarar para um FileNotFoundException ou omitir a declaração de throws, e talvez efetuando o tratamento, neste caso específico na reimplementação, ou seja, efetuando o override.

Contudo é só um exemplo que tentei dar, mencionando que podemos atribuir uma implementação utilizando a própria classe ou uma subclasse e não uma superclasse como tipo declarado. Ok!

anderline

Valeu amigo._

Criado 20 de agosto de 2006
Ultima resposta 21 de ago. de 2006
Respostas 3
Participantes 2