Como dizer ao compilador que toda ObservableList<O> que eu passar como argumento irá conter determinado método?

Tenho o seguinte método para fazer pesquisa:

public class Pesquisa {
	private static <O> ObservableList<O> pesquisarPorNome(ObservableList<O> listaObservavel, String pesquisa) {
		ObservableList<O> novaLista = FXCollections.observableArrayList();
		for(int x = 0; x<listaObservavel.size(); x++) {
			if(listaObservavel.get(x).getNome().toLowerCase().contains(pesquisa.toLowerCase()));
			novaLista.add(listaObservavel.get(x));
		}
		return novaLista;
	}

Não quero escrever esse método em todas as classes, por isso criei esse método separado que todas as classes que contém o método “getNome()” irão usar. Generalizei tudo e ta beleza, mas da erro justamente no método getNome() dizendo que não reconhece esse método. Como eu posso dizer ao compilador que toda ObservableList que eu passarei como argumento irá conter esse método ? Lembrando que passarei ObservableLists de várias classes diferentes, mas elas sempre conterão um getNome(). Obrigado.

Eu faria o seguinte:

Criaria uma classe/interface que tivesse o método getNome e faria as minhas classes estender/implementar ela

public class MinhaClasse extends MinhaClasseQueTemGetNome {

No ObservableList eu faria a tipagem assim:

ObservableList<MinhaClasseQueTemGetNome>

ou assim:

ObservableList<? extends MinhaClasseQueTemGetNome>

Caso precise fazer um cast dinâmico:

É pq só em tempo de execução que irá saber a classe que estará chegando como parametro

1 curtida

Olá, obrigado pela resposta, mas você pode me explicar oque acontece nesse código que você citou ? É inédito pra mim.

Olá, obrigado pela reposta, fiz uma interface Pesquisavel, deu tudo certo no inicio, mas na hora que fui chamar o método pesquisaPorNome(ObservableList listaObservavel, String pesquisa) passando como argumento Pesquisa.pesquisar(mainApp.getGruposData(), pesquisaTextField.getText()) Onde o getGruposData() retorna uma Observable List de Grupos, que é uma classe que implementa a interface Pesquisavel, deu tudo certo no resto, só nessa chamada de erro que está dando errado, o eclipse acusa que o método recebe um Pesquisavel, não um Grupo,sendo que Grupo implementa Pesquisavel, Porque ? Pra onde foi o Polimorfismo ?

Pode colar o código de como ficou, junto com a interface e a classe que a implementa?

O <? extends AnyClass> espera receber algum tipo que herde de AnyClass, mas cuidado, isso é diferente de .

Supondo que você tenha outras duas classes: AnyClass2 e AnyClass3.

E supondo que você tenha um método que receba como parametro um ArrayList com tipagem sem extends:

public void anyMethod(List<AnyClass> list)

Você conseguiria executar o código abaixo sem problemas, pois AnyClass2 é uma AnyClass também

list.add(anyClass2);

Enquanto que com o extends não, pois ao declarar como parametro uma lista com tipagem do tipo: ? extends AnyClass, você esta dizendo que espera receber uma lista, cuja tipagem herde de AnyClass, em outras palavras, você espera um List<AnyClass2> ou List<AnyClass3>, portanto, como o compilador não sabe quais desses dois tipos de lista virá como parâmetro, você não irá conseguira dar um add sem verificar a tipagem. Bom… ficou meio confuso kk

Quando usar um ou outro?
Sem extends você permite adicionar quaisquer tipo de objeto, desde que herde da classe pai especificada, podendo adicionar objetos do tipo AnyClass2 e AnyClass3 juntos

Com extends, você restringe a um único tipo de objeto na lista, ou será AnyClass2 ou AnyClass3

Olha o projeto no GitHub, acho que vai ficar melhor assim. Não liga para aparência ou telas sem sentido, vou arrumar isso depois. É só baixar, executar o projeto e clicar no botão “Grupos” lá é onde acontece a mágica, A classe de Pesquisa e a Interface Pesquisavel estão no pacote util, o método que usará a classe de Pesquisa está no EditGruposController no pacote view, lá tem um método chamado pesquisar() com a linha que não está funcionando comentada (o resto do código que tem lá, é um método de pesquisar temporário não-reutilizável). Muito obrigado por estar tirando um tempo seu e me ajudando ^^.

Altera de <Pesquisavel> para <? extends Pesquisavel>

O motivo disso é o seguinte:
Considere que você tenha uma classe chamada Setor que implementa Pesquisavel.

Quando você espera receber como parâmetro uma lista de uma tipagem genêrica (Pesquisavel), você realmente tem que passar como parâmetro uma List<Pesquisavel>, isso porque ao esperar uma lista do tipo List<Pesquisavel>, dentro do método você pode setar um Grupo e um Setor, mas caso você conseguisse passar como parâmetro um List<Grupo>, você não conseguiria setar um Setor na implementação do método

EDIT: Ficou meio confuso a explicação, então separei um post que aborda o tema:

Esse tipo de polimorfismo funciona para classes sem generics, ou seja:

public void metodo(Pesquisavel pesquisavel){}

metodo(setor);
metodo(grupo);
1 curtida

Obrigado mais uma vez pela resposta, mas só mais uma pergunta: eu tenho que refatorar a minha TableView<Grupos.> e/ou TableColumn para TableView<? extends Pesquisavel.> ou TableView <Pesquisavel.> ? Porque depois que resolveu o problema do getNome() deu problema no gruposTables.setItems(), o compilador estava acusando: Type mismatch: cannot convert from ObservableList to ObservableList<Grupos.>. OU se eu retorno no método um <? extends Pesquisavel>, o compilador acusa: Type mismatch: cannot convert from ObservableList to ObservableList. Nesse segundo caso a IDE sugeriu um cast e eu o fiz, parou de dar o erro, mas o gruposTable.setItems() não atualizava a tabela.

Eu não consegui rodar o seu projeto, pois não tenho o javafx aqui e ai quando fui baixar as dependencias a rede barrou.

Ai quando abri o projeto, tava tudo vermelho, pra “arrumar” isso, onde tava ObservableList troquei para List. Como a parte da chamada tinha sido resolvida, postei aqui.

Recapitulando, eu alterei o parametro do método pesquisarPorNome de ObservableList para ObservableList<? extends Pesquisavel>

Na chamada de Pesquisa.pesquisarPorNome eu passei uma lista ao invés de ObservableList

Eu editei a minha pergunta anterior e adicionei alguns detalhes. Realmente, a parte do chamado do método está resolvido e agradeço muito, o problema agora é a parte do retorno kkkk

Cola o código que esta dando erro,

Qual retorno?

O retorno do método pesquisar.

public class Pesquisa {
	public static ObservableList<? extends Pesquisavel> pesquisarPorNome(ObservableList<? extends Pesquisavel> listaObservavel, String pesquisa) {
		ObservableList<Pesquisavel> novaLista = FXCollections.observableArrayList();
		if(pesquisa.length()>0) {
		for(int x = 0; x<listaObservavel.size(); x++) {
			if(listaObservavel.get(x).getNome().toLowerCase().contains(pesquisa.toLowerCase()));
			novaLista.add(listaObservavel.get(x));
		}
		System.out.println("CHEGA AQUI");
		return novaLista;
		}else {
			return listaObservavel;
		}
	}
}

Onde está dando erro no setItems():


gruposTable.setItems( Pesquisa.pesquisarPorNome(mainApp.getGruposData(), pesquisaTextField.getText()));

O compilador acusa: The method setItems(ObservableList) in the type TableView is not applicable for the arguments (ObservableList<capture#1-of ? extends Pesquisavel>)

Ele sugere para eu fazer o seguinte cast:


gruposTable.setItems( (ObservableList<Grupos>) Pesquisa.pesquisarPorNome(mainApp.getGruposData(), pesquisaTextField.getText()));

para de dar erro e fica no warning. Porém assim a tabela não atualiza. Toda minha tabela é <Grupos.> será que tenho que refatorar o código todo para <Pesquisavel.> ou algo do tipo ?

Deixa o retorno como <Pesquisavel>

se deixar como <Pesquisavel.> dá esse erro: Type mismatch: cannot convert from ObservableList to ObservableList<Grupos.>

Vou analisar aqui pra ver se chego na solução

Muito obrigado por sua disposição ^^

Deixa a assinatura assim:

public static <T extends Pesquisavel> ObservableList<T> pesquisarPorNome(ObservableList<T> listaObservavel, String pesquisa) {

E a ObservableList você deixa a tipagem com T

ObservableList<T> novaLista

Você estava utilizando O antes, se quiser deixa O ao invés de T. Usei o T por costume e convenção.

Meu amigo, muito obrigado mesmo. Acredito que esteja tudo certo agora.
Obrigado também por essa convenção do <T.>, eu não sabia sobre ela.
A tabela continua sem atualizar após fazer a pesquisa, mas isso deve ser algum detalhe que deixei passar, depois analisarei com mais calma isso. De qualquer forma, muito obrigado.

Já consegui resolver aqui, como disse era pequeno detalhe que deixei passar despercebido kkkk tá tudo certinho agora ^^