Tengo una pregunta sobre el uso de mayúsculas y minúsculas para el instanceof
objeto:
Por ejemplo: mi problema se puede reproducir en Java:
if(this instanceof A)
doA();
else if(this instanceof B)
doB();
else if(this instanceof C)
doC():
¿Cómo se implementaría usando switch...case
?
java
switch-statement
instanceof
olidev
fuente
fuente
Respuestas:
Este es un escenario típico donde ayuda el subtipo de polimorfismo. Haz lo siguiente
A continuación, puede llamar
do()
athis
.Si no está libre de cambiar
A
,B
yC
, se podría aplicar el patrón de visitante para lograr el mismo.fuente
si absolutamente no puede codificar a una interfaz, entonces podría usar una enumeración como intermediario:
fuente
Simplemente cree un mapa donde la clase sea la clave y la funcionalidad, es decir, lambda o similar, sea el valor.
// por supuesto, refactorice esto para inicializar solo una vez
Si necesita marcar Excepciones que implementar una interfaz funcional que arroje la excepción y la use en lugar de Runnable.
fuente
instanceof
, y no, desafortunadamente, mi escenario no es uno de esos que encaja fácilmente esa caja ...)Por si acaso alguien lo leerá:
La MEJOR solución en java es:
Los GRANDES beneficios de dicho patrón son:
Simplemente hazlo como (NO hay interruptores):
En caso de que si agrega una nueva Acción llamada "d", DEBE implementar el método doAction (...)
NOTA: Este patrón se describe en el Bloch de Joshua "Java efectivo (2ª edición)"
fuente
@Override
requiere lo anterior sobre cada implementación dedoAction()
?action
usar? ¿Por una instancia externa de cascada que llamasomeFunction()
con el correctoaction
? Esto solo agrega otro nivel de indirección.No puedes La
switch
declaración solo puede contenercase
declaraciones que son constantes de tiempo de compilación y que evalúan a un entero (hasta Java 6 y una cadena en Java 7).Lo que está buscando se llama "coincidencia de patrones" en la programación funcional.
Consulte también Evitar instanceof en Java
fuente
Como se discutió en las respuestas principales, el enfoque OOP tradicional es usar polimorfismo en lugar de cambiar. Incluso hay un patrón de refactorización bien documentado para este truco: Reemplazar condicional por polimorfismo . Cada vez que busco este enfoque, me gusta implementar también un objeto nulo para proporcionar el comportamiento predeterminado.
Comenzando con Java 8, podemos usar lambdas y genéricos para darnos algo con lo que los programadores funcionales están muy familiarizados: coincidencia de patrones. No es una característica central del lenguaje, pero la biblioteca Javaslang proporciona una implementación. Ejemplo del javadoc :
No es el paradigma más natural en el mundo de Java, así que úselo con precaución. Si bien los métodos genéricos le evitarán tener que escribir el valor coincidente, nos falta una forma estándar de descomponer el objeto coincidente como, por ejemplo, con las clases de caso de Scala .
fuente
Sé que es muy tarde, pero para futuros lectores ...
Tenga cuidado con los enfoques anteriores que se basan solo en el nombre de la clase de A , B , C ...:
A menos que pueda garantizar que A , B , C ... (todas las subclases o implementadores de Base ) sean finales , las subclases de A , B , C ... no se tratarán.
Aunque el enfoque if, elseif, elseif .. es más lento para un gran número de subclases / implementadores, es más preciso.
fuente
Desafortunadamente, no es posible fuera de la caja ya que la declaración de cambio de caso espera una expresión constante. Para superar esto, una forma sería usar valores de enumeración con los nombres de clase, por ejemplo
Con eso es posible usar la declaración de cambio como esta
fuente
No, no hay forma de hacer esto. Sin embargo, lo que quizás desee hacer es considerar el polimorfismo como una forma de manejar este tipo de problemas.
fuente
El uso de declaraciones de cambio como esta no es la forma orientada a objetos. En su lugar, debes usar el poder del polimorfismo . Simplemente escribe
Habiendo configurado previamente una clase base:
que es la clase base para
A
,B
yC
:fuente
Esto funcionará más rápido y tendrá sentido en caso de
que tenga muchos casos
, el proceso se ejecuta en un contexto sensible al rendimiento
fuente
No puede un switch solo funciona con los tipos byte, short, char, int, String y enumerados (y las versiones de objeto de las primitivas, también depende de su versión de Java, las cadenas se pueden
switch
editar en Java 7)fuente
Personalmente me gusta el siguiente código Java 1.8:
Saldrá:
El código de muestra usa cadenas, pero puede usar cualquier tipo de objeto, incluida la clase. p.ej
.myCase(this.getClass(), (o) -> ...
Necesita el siguiente fragmento:
fuente
Java ahora le permite cambiar a la manera del OP. Lo llaman Pattern Matching para cambiar. Actualmente está en borrador, pero al ver cuánto trabajo han estado poniendo en los interruptores recientemente, creo que pasará. El ejemplo dado en el JEP es
o usando su sintaxis lambda y devolviendo un valor
De cualquier manera, han estado haciendo cosas geniales con los interruptores.
fuente
Si puede manipular la interfaz común, puede agregar una enumeración y hacer que cada clase devuelva un valor único. No necesitará instanceof o un patrón de visitante.
Para mí, la lógica tenía que estar escrita en la declaración de cambio, no el objeto en sí. Esta fue mi solución:
ClassA, ClassB, and ClassC implement CommonClass
Interfaz:
Enum:
Impl:
Si está en Java 7, puede poner valores de cadena para la enumeración y el bloque de mayúsculas y minúsculas seguirá funcionando.
fuente
value
campo es redundante si solo desea distinguir las constantes de enumeración; puede usar las constantes directamente (como lo hace).Qué tal esto ?
fuente
this.getSimpleName()
No estoy seguro de si el póster está confundido con JS (sí, está usando la consola, jeje).Creo que hay razones para usar una declaración de cambio. Si está utilizando el código generado por xText, tal vez. O otro tipo de clases generadas por EMF.
devuelve una cadena del nombre de implementación de clase. es decir: org.eclipse.emf.ecore.util.EcoreUtil
devuelve la representación simple, es decir: EcoreUtil
fuente
switch
comocase
condición porque no es un valor constanteSi necesita "cambiar" a través del tipo de clase de "este" objeto, esta respuesta es la mejor https://stackoverflow.com/a/5579385/2078368
Pero si necesita aplicar "cambiar" a cualquier otra variable. Sugeriría otra solución. Defina la siguiente interfaz:
Implemente esta interfaz en cada clase que desee "cambiar". Ejemplo:
Después de eso, puede usarlo de la siguiente manera:
Lo único que debería importarle es mantener los "tipos" únicos en todas las clases que implementan ClassTypeInterface. No es un gran problema, porque en caso de cualquier intersección, recibirá un error en tiempo de compilación para la instrucción "switch-case".
fuente
TYPE
, puede usar una enumeración y se garantiza la unicidad (como se hace en esta respuesta ). Sin embargo, con cualquiera de los enfoques, tendrá que refactorizar en dos lugares cuando cambie el nombre.TYPE = "A"
al cambiar el nombre. Especialmente si está fuera de la clase correspondiente, uno también podría olvidarlo al hacerlo manualmente. IntelliJ también encuentra las ocurrencias del nombre de la clase en cadenas o comentarios, pero eso es solo una búsqueda de texto (en lugar de mirar el árbol de sintaxis) y, por lo tanto, incluye falsos positivos.Aquí hay una forma funcional de lograrlo en Java 8 usando http://www.vavr.io/
fuente
Si bien no es posible escribir una declaración de cambio, es posible ramificarse a un procesamiento específico para cada tipo dado. Una forma de hacerlo es utilizar un mecanismo estándar de despacho doble. Un ejemplo en el que queremos "cambiar" según el tipo es el mapeador de excepciones de Jersey, donde necesitamos mapear multitud de excepciones a las respuestas de error. Si bien para este caso específico probablemente haya una mejor manera (es decir, usar un método polimórfico que traduzca cada excepción a una respuesta de error), el uso del mecanismo de doble despacho sigue siendo útil y práctico.
Entonces, siempre que se necesite el "interruptor", puede hacerlo de la siguiente manera:
fuente
Crear una enumeración con nombres de clase.
Encuentra el nombre de la clase del objeto. Escriba un caso de cambio sobre la enumeración.
Espero que esto ayude.
fuente
El Marco de modelado de Eclipse tiene una idea interesante que también considera la herencia. El concepto básico se define en la interfaz Switch : el cambio se realiza invocando el método doSwitch .
Lo que es realmente interesante es la implementación. Para cada tipo de interés, un
El método debe implementarse (con una implementación predeterminada que devuelve nulo). La implementación de doSwitch intentará llamar a todos los métodos caseXXX en el objeto para toda su jerarquía de tipos. Algo en las líneas de:
El marco real utiliza una identificación entera para cada clase, por lo que la lógica es en realidad un interruptor puro:
Puede ver una implementación completa de ECoreSwitch para tener una mejor idea.
fuente
hay una forma aún más simple de emular una estructura de conmutador que usa instanceof, lo haces creando un bloque de código en tu método y nombrándolo con una etiqueta. Luego usas estructuras if para emular las declaraciones de casos. Si un caso es verdadero, entonces usa la ruptura LABEL_NAME para salir de su estructura de interruptor improvisada.
fuente
if
...else if
código proporcionado por el OP?if
...else if
con declaraciones "goto", que es la forma incorrecta de implementar el flujo de control en lenguajes como Java.