Eu tenho duas interfaces em Java (versão 8) que são muito semelhantes. Não posso alterar as interfaces e não posso alterar as classes que as implementam.
public interface A {
int get();
}
public interface B {
int get();
int somethingelse();
}
Agora eu tenho uma função que sua implementação se encaixa nas duas interfaces (quase). Eu quero fazer algo assim:
public int foo((A | B) p) {
int ret = 0;
if (p instanceof B) {
ret = p.somthingelse();
}
return ret + p.get();
}
Não quero usar a inspeção porque esta função está no pipeline principal do meu programa. Eu quero que ele tenha um bom desempenho. É possível fazer isso em Java?
Editar:
Uma solução simples será copiar / colar foo()
e implementá-lo de maneira diferente para cada interface. Mas, na realidade, foo()
as interfaces são muito mais longas que isso e estou tentando evitar a duplicação de código.
get()
em comum. Este é obviamente um exemplo simplificado. Na realidade, eles têm mais funções em comum.public
acessador é redundante para métodos de interface. E você quis dizer eminstanceof
vez deimplements
?Respostas:
Infelizmente, não há como criar esse tipo de relacionamento retroativo entre dois tipos não relacionados.
Se você puder alterar
foo()
e suas invocações, poderá usar interfaces funcionais que correspondem às assinaturas que você invoca dentrofoo
. Estou usandoIntSupplier
aqui, com expressões lambda correspondentes usando implementações concretas deA
eB
.Digamos que você tenha estas implementações:
Você pode mudar
foo
para algo como:E chame assim:
fonte
foo()
para cada interface e ligue para o seufoo()
fornecedor correspondente. Deseja adicionar isso ou deseja que eu edite sua resposta?if
lógica deve permanecer dentrofoo()
. Mas sim, você pode fazer isso definitivamente, se for apropriado.IntSupplier
sugestão nesta resposta. Além disso, oBImpl
(ou simplesmenteB
) não pode ser usado como um FunctionalInterface, dado mais de um método abstrato. Além disso, a partir de um comentário , a afirmação " dois tipos não relacionados " não é verdadeira. Nitpick:IntSupplier get
não é usado no seu código.B
não está sendo usado como uma interface funcional.b:somethingelse
é uma referência de método paraIntSupplier
este caso (eu sugiro que você compile o código). E sim,A
eB
são dois tipos completamente independentes. E sobre a solução geral, acho que entendo que você acha um pouco estranho. Posso supor que existem abordagens mais refinadas, mas não muitas que evitam a refatoração que o OP não pode pagar.A única maneira que eu posso imaginar é isso:
fonte
Além disso, o Java não suporta isso diretamente, mas você pode criar manualmente um "wrapper de união de tipo". Algo assim:
Você também pode adicionar algumas funções de inspeção como
hasSomethingElse()
, se não houver um valor padrão apropriado para retornar, como0
acima.fonte