У меня есть вопрос об использовании регистра переключателя для instanceof
объекта:
Например: моя проблема может быть воспроизведена на Java:
if(this instanceof A)
doA();
else if(this instanceof B)
doB();
else if(this instanceof C)
doC():
Как бы это было реализовано с помощью switch...case
?
java
switch-statement
instanceof
olidev
источник
источник
Ответы:
Это типичный сценарий, в котором помогает полиморфизм подтипа. Сделайте следующее
Тогда вы можете просто позвонить
do()
поthis
.Если вы не можете свободно изменять
A
,B
иC
, вы можете применить шаблон посетителя для достижения того же.источник
если вы абсолютно не можете кодировать интерфейс, вы можете использовать enum в качестве посредника:
источник
Просто создайте карту, где класс является ключом, а функциональность, то есть лямбда или аналогичная, является значением.
// конечно, рефакторинг это только один раз инициализировать
Если вам нужно проверить Исключения, тогда реализуйте FunctionalInterface, который выдает Исключение и использует его вместо Runnable.
источник
instanceof
, и нет, мой сценарий, к сожалению, не один из тех, которые легко вписываются в та коробка ...)На всякий случай, если кто-то прочтет это:
Лучшее решение в Java это:
БОЛЬШИМИ преимуществами такой модели являются:
Вы просто делаете это как (никаких переключателей вообще):
В случае, если вы добавляете новое действие под названием «d», вы ДОЛЖНЫ реализовать метод doAction (...)
ПРИМЕЧАНИЕ. Этот шаблон описан в блоке Джошуа «Эффективная Java (2-е издание)».
источник
@Override
предписанная выше каждой реализацииdoAction()
?action
использовать? По внешнему экземпляру каскада, который вызываетsomeFunction()
с правильнымaction
? Это просто добавляет еще один уровень косвенности.Ты не можешь
switch
Заявление может содержать толькоcase
утверждение , которые компиляция константы времени и которые являются целым числом (до Java 6 и строки в Java 7).То, что вы ищете, называется «сопоставление с образцом» в функциональном программировании.
Смотрите также Как избежать instanceof в Java
источник
Как обсуждалось в верхних ответах, традиционный подход ООП заключается в использовании полиморфизма вместо переключения. Для этого трюка есть даже хорошо документированный шаблон рефакторинга: Заменить Условный на Полиморфизм . Всякий раз, когда я достигаю этого подхода, мне нравится также реализовывать объект Null для обеспечения поведения по умолчанию.
Начиная с Java 8, мы можем использовать лямбды и дженерики, чтобы дать нам кое-что, с чем функциональные программисты хорошо знакомы: сопоставление с образцом. Это не базовая языковая функция, но библиотека Javaslang предоставляет одну реализацию. Пример из Javadoc :
Это не самая естественная парадигма в мире Java, поэтому используйте ее с осторожностью. Хотя универсальные методы избавят вас от необходимости типизировать совпадающее значение, мы упускаем стандартный способ декомпозиции сопоставляемого объекта, как , например, в классах case Scala .
источник
Я знаю, что это очень поздно, но для будущих читателей ...
Остерегайтесь вышеприведенных подходов, основанных только на названии класса A , B , C ...:
Если вы не можете гарантировать, что A , B , C ... (все подклассы или реализации Base ) являются окончательными, то подклассы A , B , C ... не будут рассматриваться.
Хотя подход if, elseif, elseif .. медленнее для большого числа подклассов / реализаторов, он более точен.
источник
К сожалению, это невозможно из коробки, поскольку оператор switch-case ожидает константное выражение. Чтобы преодолеть это, можно использовать значения перечислений с именами классов, например:
С этим можно использовать оператор switch следующим образом
источник
Нет, нет способа сделать это. Однако вы, возможно, захотите рассмотреть полиморфизм как способ решения подобных проблем.
источник
Использование таких операторов переключения не является объектно-ориентированным способом. Вместо этого вы должны использовать силу полиморфизма . Просто пиши
Предварительно настроив базовый класс:
который является базовым классом для
A
,B
иC
:источник
Это будет работать быстрее и иметь смысл в случае, если у
вас есть относительно много «дел»,
процесс выполняется в контексте, чувствительном к производительности
источник
Вы не можете переключаться, работает только с байтовым, коротким, типом char, int, String и перечисляемым типом (и объектными версиями примитивов, это также зависит от вашей версии Java, строки можно
switch
редактировать в Java 7)источник
Мне лично нравится следующий код Java 1.8:
Будет выводить:
В примере кода используются строки, но вы можете использовать любой тип объекта, включая класс. например
.myCase(this.getClass(), (o) -> ...
Требуется следующий фрагмент:
источник
Java теперь позволяет переключаться в порядке OP. Они называют это Pattern Matching for switch. В настоящее время он находится на драфте, но, видя, сколько работы они вкладывают в коммутаторы в последнее время, я думаю, что он пройдет Пример, приведенный в JEP:
или используя их лямбда-синтаксис и возвращая значение
так или иначе, они делали классные вещи с выключателями.
источник
Если вы можете манипулировать общим интерфейсом, вы можете добавить add в enum и заставить каждый класс возвращать уникальное значение. Вам не понадобится instanceof или шаблон посетителя.
Для меня логика должна быть записана в операторе switch, а не сам объект. Это было мое решение:
ClassA, ClassB, and ClassC implement CommonClass
Интерфейс:
Enum:
Impl:
Если вы используете Java 7, вы можете поместить строковые значения для enum, и блок регистра переключателей все равно будет работать.
источник
value
Поле является излишним , если вы хотите , чтобы отличить константы перечислений - вы можете использовать константы непосредственно (как и вы).Как насчет этого ?
источник
this.getSimpleName()
Not sure, если плакат перепутан с JS (да, он использует консоль, хе-хе).Я думаю, что есть причины использовать оператор switch. Если вы используете сгенерированный xText код, возможно. Или другой вид классов, генерируемых EMF.
возвращает строку с именем реализации класса. то есть: org.eclipse.emf.ecore.util.EcoreUtil
возвращает простое представление, то есть: EcoreUtil
источник
switch
какcase
условие, потому что это не постоянное значениеЕсли вам нужно «переключиться» через тип класса «this», этот ответ является лучшим https://stackoverflow.com/a/5579385/2078368
Но если вам нужно применить «переключатель» к любой другой переменной. Я бы предложил другое решение. Определите следующий интерфейс:
Реализуйте этот интерфейс в каждом классе, который вы хотите «переключить». Пример:
После этого вы можете использовать его следующим образом:
Единственное, о чем вы должны заботиться - сохранять уникальность «типов» во всех классах, реализующих ClassTypeInterface. Это не большая проблема, потому что в случае любого пересечения вы получаете ошибку времени компиляции для оператора "switch-case".
источник
TYPE
вы можете использовать enum, и уникальность гарантируется (как сделано в этом ответе ). Однако при любом из подходов вам придется проводить рефакторинг в двух местах при переименовании.TYPE = "A"
при переименовании. Особенно, если он находится за пределами соответствующего класса, можно также забыть об этом при выполнении этого вручную. На самом деле IntelliJ также находит вхождения строк в именах строк или комментариев, но это всего лишь текстовый поиск (вместо просмотра синтаксического дерева), и, таким образом, он содержит ложные срабатывания.Вот функциональный способ сделать это в Java 8, используя http://www.vavr.io/
источник
Несмотря на то, что невозможно написать оператор switch, возможно перейти к определенной обработке для каждого данного типа. Один из способов сделать это - использовать стандартный механизм двойной отправки. Примером, в котором мы хотим «переключаться» на основе типа, является сопоставитель исключений Jersey, где нам нужно сопоставить множество исключений с ответами об ошибках. В то время как для этого конкретного случая, вероятно, существует лучший способ (то есть использование полиморфного метода, который переводит каждое исключение в ответ об ошибке), использование механизма двойной отправки все еще полезно и практично.
Затем, когда бы ни понадобился «переключатель», вы можете сделать это следующим образом:
источник
Создайте Enum с именами классов.
Найдите имя класса объекта. Напишите регистр переключателя над перечислением.
Надеюсь это поможет.
источник
Eclipse Modeling Framework имеет интересную идею, которая также учитывает наследование. Основная концепция определена в интерфейсе Switch : переключение выполняется с помощью метода doSwitch .
Что действительно интересно, так это реализация. Для каждого типа интереса,
метод должен быть реализован (с реализацией по умолчанию, возвращающей ноль). Реализация doSwitch попытается вызвать все методы caseXXX для объекта для всей его иерархии типов. Что-то в строках:
Фактическая структура использует целочисленный идентификатор для каждого класса, таким образом, логика - фактически чистый переключатель:
Вы можете посмотреть на полную реализацию ECoreSwitch, чтобы получить лучшую идею.
источник
Существует еще более простой способ эмуляции структуры переключателя, использующей instanceof, вы делаете это, создавая блок кода в своем методе и называя его меткой. Затем вы используете структуры if для эмуляции операторов case. Если дело истинно, то вы используете разрыв LABEL_NAME, чтобы выйти из структуры временного переключателя.
источник
if
...else if
код, указанный ОП?if
...else if
на операторы "goto", что является неправильным способом реализации потока управления в таких языках, как Java.