J'ai une question d'utiliser le boîtier de commutateur pour l' instanceof
objet:
Par exemple: mon problème peut être reproduit en Java:
if(this instanceof A)
doA();
else if(this instanceof B)
doB();
else if(this instanceof C)
doC():
Comment serait-il mis en œuvre en utilisant switch...case
?
java
switch-statement
instanceof
olidev
la source
la source
Réponses:
Il s'agit d'un scénario typique où le polymorphisme de sous-type aide. Procédez comme suit
Ensuite , vous pouvez simplement appeler
do()
surthis
.Si vous n'êtes pas libre de changer
A
,B
etC
, vous pouvez appliquer le modèle de visiteur pour obtenir le même.la source
si vous ne pouvez absolument pas coder sur une interface, vous pouvez utiliser une énumération comme intermédiaire:
la source
Il suffit de créer une carte où la classe est la clé et la fonctionnalité, c'est-à-dire lambda ou similaire, est la valeur.
// bien sûr, refactorisez ceci pour ne l'initialiser qu'une seule fois
Si vous avez besoin d'exceptions vérifiées, implémentez une FunctionalInterface qui lève l'exception et utilisez-la à la place de Runnable.
la source
instanceof
, et non, mon scénario n'est malheureusement pas de ceux qui s'intègrent facilement dans cette boîte ...)Juste au cas où quelqu'un le lirait:
La MEILLEURE solution en java est:
Les GRANDS avantages d'un tel modèle sont:
Vous le faites comme (AUCUN interrupteurs du tout):
Dans le cas où si vous ajoutez une nouvelle action appelée "d", vous DEVEZ imlement la méthode doAction (...)
REMARQUE: ce modèle est décrit dans le Bloch de Joshua "Effective Java (2nd Edition)"
la source
@Override
requis au-dessus de chaque implémentation dedoAction()
?action
utiliser? Par une instance externe de cascade qui appellesomeFunction()
avec le bonaction
? Cela ajoute juste un autre niveau d'indirection.Tu ne peux pas. L'
switch
instruction ne peut contenir que descase
instructions qui sont des constantes de temps de compilation et qui s'évaluent en un entier (jusqu'à Java 6 et une chaîne en Java 7).Ce que vous recherchez est appelé "pattern matching" dans la programmation fonctionnelle.
Voir aussi Éviter instanceof en Java
la source
Comme indiqué dans les principales réponses, l'approche OOP traditionnelle consiste à utiliser le polymorphisme au lieu du commutateur. Il existe même un modèle de refactorisation bien documenté pour cette astuce: remplacer le conditionnel par le polymorphisme . Chaque fois que j'atteins cette approche, j'aime également implémenter un objet Null pour fournir le comportement par défaut.
À partir de Java 8, nous pouvons utiliser des lambdas et des génériques pour nous donner quelque chose que les programmeurs fonctionnels connaissent très bien: la mise en correspondance de modèles. Ce n'est pas une fonctionnalité de langage de base, mais la bibliothèque Javaslang fournit une implémentation. Exemple du javadoc :
Ce n'est pas le paradigme le plus naturel du monde Java, alors utilisez-le avec prudence. Alors que les méthodes génériques vous éviteront d'avoir à transtyper la valeur correspondante, il nous manque une façon standard de décomposer l'objet correspondant comme avec les classes de cas de Scala par exemple.
la source
Je sais que c'est très tard mais pour les futurs lecteurs ...
Méfiez-vous des approches ci-dessus qui ne sont basées que sur le nom de la classe A , B , C ...:
A moins que vous ne puissiez garantir que A , B , C ... (toutes les sous-classes ou implémenteurs de Base ) sont finales, puis les sous-classes de A , B , C ... ne seront pas traitées.
Même si l' approche if, elseif, elseif .. est plus lente pour un grand nombre de sous-classes / implémenteurs, elle est plus précise.
la source
Malheureusement, il n'est pas possible de sortir de la boîte car l'instruction switch-case attend une expression constante. Pour surmonter cela, une façon serait d'utiliser des valeurs d'énumération avec les noms de classe, par exemple
Avec cela, il est possible d'utiliser l'instruction switch comme ceci
la source
Non, il n'y a aucun moyen de le faire. Ce que vous pourriez vouloir faire est cependant de considérer le polymorphisme comme un moyen de gérer ce genre de problèmes.
la source
L'utilisation d'instructions de commutation comme celle-ci n'est pas orientée objet. Vous devriez plutôt utiliser le pouvoir du polymorphisme . Ecrivez simplement
Après avoir configuré une classe de base:
qui est la classe de base pour
A
,B
etC
:la source
Cela fonctionnera plus rapidement et fera sence au cas où
- vous avez relativement de nombreux cas
- le processus est exécuté dans un contexte sensible aux performances
la source
Vous ne pouvez pas un commutateur ne fonctionne qu'avec les types byte, short, char, int, String et énumérés (et les versions d'objet des primitives, cela dépend aussi de votre version java, les chaînes peuvent être
switch
éditées dans java 7)la source
Personnellement, j'aime le code Java 1.8 suivant:
Sortira:
L'exemple de code utilise des chaînes mais vous pouvez utiliser n'importe quel type d'objet, y compris la classe. par exemple
.myCase(this.getClass(), (o) -> ...
Nécessite l'extrait de code suivant:
la source
Java vous permet désormais de basculer à la manière de l'OP. Ils l'appellent Pattern Matching pour switch. Il est actuellement en cours de rédaction, mais vu combien de travail ils ont mis dans les commutateurs récemment, je pense que cela va passer. L'exemple donné dans le JEP est
ou en utilisant leur syntaxe lambda et en retournant une valeur
de toute façon, ils ont fait des trucs sympas avec des interrupteurs.
la source
Si vous pouvez manipuler l'interface commune, vous pouvez ajouter une énumération et demander à chaque classe de renvoyer une valeur unique. Vous n'aurez pas besoin de instanceof ou d'un modèle de visiteur.
Pour moi, la logique devait être dans l'écrit dans l'instruction switch, pas l'objet lui-même. C'était ma solution:
ClassA, ClassB, and ClassC implement CommonClass
Interface:
Enum:
Impl:
Si vous utilisez Java 7, vous pouvez mettre des valeurs de chaîne pour l'énumération et le bloc de casse de commutateur fonctionnera toujours.
la source
value
champ est redondant si vous souhaitez uniquement distinguer les constantes d'énumération - vous pouvez utiliser les constantes directement (comme vous le faites).Que dis-tu de ça ?
la source
this.getSimpleName()
Je ne sais pas si l'affiche est confondue avec JS (ouais, il utilise la console, hehe).Je pense qu'il y a des raisons d'utiliser une instruction switch. Si vous utilisez peut-être du code généré par xText. Ou un autre type de classes générées par EMF.
renvoie une chaîne du nom d'implémentation de classe. c'est-à-dire: org.eclipse.emf.ecore.util.EcoreUtil
renvoie la représentation simple ie: EcoreUtil
la source
switch
commecase
condition car ce n'est pas une valeur constanteSi vous devez "basculer" via le type de classe de "cet" objet, cette réponse est la meilleure https://stackoverflow.com/a/5579385/2078368
Mais si vous devez appliquer "switch" à toute autre variable. Je proposerais une autre solution. Définissez l'interface suivante:
Implémentez cette interface dans chaque classe que vous souhaitez "basculer". Exemple:
Après cela, vous pouvez l'utiliser de la manière suivante:
La seule chose à laquelle vous devriez vous soucier - garder les "types" uniques dans toutes les classes implémentant ClassTypeInterface. Ce n'est pas un gros problème, car en cas d'intersection, vous recevez une erreur de compilation pour l'instruction "switch-case".
la source
TYPE
, vous pouvez utiliser une énumération et l'unicité est garantie (comme cela est fait dans cette réponse ). Cependant, avec l'une des approches, vous devrez refactoriser à deux endroits lorsque vous effectuez un changement de nom.TYPE = "A"
lors du renommage. Surtout si elle est en dehors de la classe correspondante, on peut également l'oublier en la faisant manuellement. IntelliJ trouve également les occurrences du nom de classe dans des chaînes ou des commentaires, mais ce n'est qu'une recherche de texte (au lieu de regarder l'arbre de syntaxe) et inclut donc les faux positifs.Voici une manière fonctionnelle de l'accomplir dans Java 8 en utilisant http://www.vavr.io/
la source
Bien qu'il ne soit pas possible d'écrire une instruction switch, il est possible de passer à un traitement spécifique pour chaque type donné. Une façon de procéder consiste à utiliser un mécanisme de double répartition standard. Un exemple où nous voulons «basculer» en fonction du type est le mappeur d'exceptions Jersey où nous devons mapper une multitude d'exceptions aux réponses aux erreurs. Alors que dans ce cas spécifique, il existe probablement un meilleur moyen (c'est-à-dire en utilisant une méthode polymorphe qui traduit chaque exception en une réponse d'erreur), l'utilisation du mécanisme de double répartition est toujours utile et pratique.
Ensuite, partout où le "commutateur" est nécessaire, vous pouvez le faire comme suit:
la source
Créez une énumération avec des noms de classe.
Recherchez le nom de classe de l'objet. Écrivez un commutateur sur l'énumération.
J'espère que cela t'aides.
la source
Le cadre de modélisation Eclipse a une idée intéressante qui considère également l'héritage. Le concept de base est défini dans l' interface Switch : la commutation se fait en appelant le doSwitch méthode .
Ce qui est vraiment intéressant, c'est l'implémentation. Pour chaque type d'intérêt, un
doit être implémentée (avec une implémentation par défaut renvoyant null). L' implémentation doSwitch tentera d'appeler toutes les méthodes caseXXX sur l'objet pour toute sa hiérarchie de types. Quelque chose dans les lignes de:
Le cadre réel utilise un identifiant entier pour chaque classe, donc la logique est en fait un simple commutateur:
Vous pouvez consulter une implémentation complète de l' ECoreSwitch pour vous faire une meilleure idée.
la source
il existe un moyen encore plus simple d'émuler une structure de commutateur qui utilise instanceof, vous pouvez le faire en créant un bloc de code dans votre méthode et en le nommant avec une étiquette. Vous utilisez ensuite les structures if pour émuler les instructions case. Si un cas est vrai, vous utilisez la pause LABEL_NAME pour sortir de votre structure de commutateur de fortune.
la source
if
...else if
code donné par l'OP?if
...else if
par des instructions "goto", ce qui est la mauvaise façon d'implémenter le flux de contrôle dans des langages comme Java.