Eu tenho uma questão de usar switch case para instanceof
objeto:
Por exemplo: meu problema pode ser reproduzido em Java:
if(this instanceof A)
doA();
else if(this instanceof B)
doB();
else if(this instanceof C)
doC():
Como seria implementado usando switch...case
?
java
switch-statement
instanceof
olidev
fonte
fonte
Respostas:
Esse é um cenário típico em que o polimorfismo de subtipo ajuda. Faça o seguinte
Em seguida, você pode simplesmente chamar
do()
nothis
.Se você não está livre para mudar
A
,B
eC
, você poderia aplicar o padrão do visitante para alcançar o mesmo.fonte
se você absolutamente não puder codificar para uma interface, poderá usar uma enumeração como intermediário:
fonte
Basta criar um mapa em que a classe seja a chave e a funcionalidade, por exemplo, lambda ou similar, seja o valor.
// é claro, refatorar isso para inicializar apenas uma vez
Se você precisar verificar exceções, implemente um FunctionalInterface que lança a exceção e use-o em vez de Runnable.
fonte
instanceof
, e não, meu cenário infelizmente não é um daqueles que se encaixam facilmente essa caixa ...)Apenas no caso de alguém ler:
A melhor solução em java é:
Os GRANDES benefícios desse padrão são:
Você apenas faz isso (sem interruptores):
Caso você adicione uma nova ação chamada "d", DEVE aplicar o método doAction (...)
NOTA: Esse padrão é descrito no livro de Joshua Bloch "Effective Java (2nd Edition)"
fonte
@Override
necessário acima de cada implementação dedoAction()
?action
usar? Por uma instância externa de cascata que chamasomeFunction()
com o corretoaction
? Isso apenas adiciona outro nível de indireção.Você não pode. A
switch
instrução pode conter apenascase
instruções que são constantes de tempo de compilação e avaliadas como um número inteiro (até Java 6 e uma sequência em Java 7).O que você está procurando é chamado de "correspondência de padrões" na programação funcional.
Consulte também Evitando instanceof em Java
fonte
Conforme discutido nas principais respostas, a abordagem tradicional de POO é usar polimorfismo em vez de alternar. Existe até um padrão de refatoração bem documentado para esse truque: Substituir Condicional pelo Polimorfismo . Sempre que busco essa abordagem, também gosto de implementar um objeto Nulo para fornecer o comportamento padrão.
A partir do Java 8, podemos usar lambdas e genéricos para fornecer algo que os programadores funcionais estão familiarizados com: correspondência de padrões. Não é um recurso de linguagem principal, mas a biblioteca Javaslang fornece uma implementação. Exemplo do javadoc :
Não é o paradigma mais natural do mundo Java, portanto, use-o com cautela. Embora os métodos genéricos evitem que você tenha que digitar o valor correspondente, estamos perdendo uma maneira padrão de decompor o objeto correspondente, como nas classes de caso do Scala, por exemplo.
fonte
Sei que é muito tarde, mas para futuros leitores ...
Cuidado com as abordagens acima, baseadas apenas no nome da classe de A , B , C ...:
A menos que você possa garantir que A , B , C ... (todas as subclasses ou implementadores de Base ) sejam finais , as subclasses de A , B , C ... não serão tratadas.
Embora a abordagem if, elseif, elseif .. seja mais lenta para um grande número de subclasses / implementadores, é mais precisa.
fonte
Infelizmente, isso não é possível imediatamente, pois a instrução switch-case espera uma expressão constante. Para superar isso, uma maneira seria usar valores de enumeração com os nomes das classes, por exemplo
Com isso é possível usar a instrução switch como esta
fonte
Não, não há como fazer isso. O que você pode querer fazer é considerar o polimorfismo como uma maneira de lidar com esse tipo de problema.
fonte
Usar instruções de opção como essa não é a maneira orientada a objetos. Você deve usar o poder do polimorfismo . Basta escrever
Tendo configurado anteriormente uma classe base:
que é a classe de base para
A
,B
eC
:fonte
Isso funcionará mais rápido e fará sentido caso
- você tenha relativamente "casos"
- o processo seja executado em um contexto sensível ao desempenho
fonte
Você não pode alternar apenas com os tipos byte, short, char, int, String e enumerados (e as versões de objeto das primitivas, isso também depende da sua versão java. As strings podem ser
switch
editadas no java 7)fonte
Eu pessoalmente gosto do seguinte código Java 1.8:
Saída:
O código de exemplo usa Strings, mas você pode usar qualquer tipo de objeto, incluindo Classe. por exemplo
.myCase(this.getClass(), (o) -> ...
Precisa do seguinte snippet:
fonte
O Java agora permite que você alterne da maneira do OP. Eles chamam de Correspondência de Padrões para switch. Atualmente, ele está em rascunho, mas vendo quanto trabalho eles colocaram em switches recentemente, acho que ele será executado. O exemplo dado no JEP é
ou usando sua sintaxe lambda e retornando um valor
de qualquer maneira, eles estão fazendo coisas legais com os interruptores.
fonte
Se você pode manipular a interface comum, pode adicionar uma enumeração e fazer com que cada classe retorne um valor exclusivo. Você não precisará de instanceof ou um padrão de visitante.
Para mim, a lógica precisava estar escrita na instrução switch, não no objeto em si. Esta foi a minha solução:
ClassA, ClassB, and ClassC implement CommonClass
Interface:
Enum:
Impl:
Se você estiver no java 7, poderá colocar valores de sequência para a enumeração e o bloco de caixa do comutador ainda funcionará.
fonte
value
campo é redundante se você deseja distinguir apenas as constantes enum - você pode usá-las diretamente (como você faz).Que tal agora ?
fonte
this.getSimpleName()
Não tenho certeza se o pôster está confuso com JS (sim, ele está usando console, hehe).Eu acho que existem razões para usar uma instrução switch. Se você estiver usando o código gerado pelo xText, talvez. Ou outro tipo de classes geradas pela EMF.
retorna uma String do nome de implementação da classe. ou seja: org.eclipse.emf.ecore.util.EcoreUtil
retorna a representação simples, ou seja: EcoreUtil
fonte
switch
comocase
condição porque não é valor constanteSe você precisar "alternar" pelo tipo de classe do objeto "this", esta resposta é a melhor https://stackoverflow.com/a/5579385/2078368
Mas se você precisar aplicar "switch" a qualquer outra variável. Eu sugeriria outra solução. Defina a seguinte interface:
Implemente essa interface em todas as classes que você deseja "alternar". Exemplo:
Depois disso, você pode usá-lo da seguinte maneira:
A única coisa com a qual você deve se preocupar - mantenha os "tipos" exclusivos em todas as classes que implementam o ClassTypeInterface. Não é um grande problema, porque, no caso de qualquer interseção, você recebe um erro em tempo de compilação para a instrução "switch-case".
fonte
TYPE
, você pode usar uma enumeração e a exclusividade é garantida (como feito nesta resposta ). No entanto, com qualquer uma das abordagens, você precisará refatorar em dois lugares ao renomear.TYPE = "A"
ao renomear. Especialmente se estiver fora da classe correspondente, também é possível esquecê-lo ao fazê-lo manualmente. Na verdade, o IntelliJ também encontra as ocorrências do nome da classe em seqüências de caracteres ou comentários, mas isso é apenas uma pesquisa de texto (em vez de olhar para a árvore de sintaxe) e, portanto, inclui falsos positivos.Aqui está uma maneira funcional de realizá-lo no Java 8 usando http://www.vavr.io/
fonte
Embora não seja possível escrever uma instrução switch, é possível ramificar para um processamento específico para cada tipo especificado. Uma maneira de fazer isso é usar o mecanismo padrão de despacho duplo. Um exemplo em que queremos "alternar" com base no tipo é o mapeador de exceções de Jersey, onde precisamos mapear várias exceções para respostas de erro. Embora neste caso específico exista provavelmente uma maneira melhor (por exemplo, usar um método polimórfico que traduza cada exceção em uma resposta de erro), o uso do mecanismo de despacho duplo ainda é útil e prático.
Então, sempre que o "switch" for necessário, você poderá fazer o seguinte:
fonte
Crie um Enum com nomes de classe.
Encontre o nome da classe do objeto. Escrever um interruptor de caso sobre o enum.
Espero que isto ajude.
fonte
O Eclipse Modeling Framework tem uma ideia interessante que também considera herança. O conceito básico é definido na interface Switch : a troca é feita invocando o método doSwitch .
O que é realmente interessante é a implementação. Para cada tipo de interesse, um
O método deve ser implementado (com uma implementação padrão retornando nulo). A implementação doSwitch tentará chamar todos os métodos caseXXX no objeto para toda a sua hierarquia de tipos. Algo nas linhas de:
A estrutura atual usa um ID inteiro para cada classe, portanto, a lógica é realmente uma opção pura:
Você pode ver uma implementação completa do ECoreSwitch para ter uma idéia melhor.
fonte
existe uma maneira ainda mais simples de emular uma estrutura de switch que usa instanceof, você faz isso criando um bloco de código no seu método e nomeando-o com um rótulo. Então você usa estruturas if para emular as instruções de caso. Se um caso for verdadeiro, use a interrupção LABEL_NAME para sair da sua estrutura de comutador improvisado.
fonte
if
...else if
código fornecido pelo OP?if
...else if
por instruções "goto", que é a maneira errada de implementar o fluxo de controle em linguagens como Java.