#java #enums
#java #перечисления
Вопрос:
У меня есть два перечисления в двух разных классах (показано ниже):
enum State {
NOCAR, SOLD, TO_BUY, TOYOTA, HONDA, NISSAN, BMW, MERCEDES, NO_MONEY
}
enum Car {
TOYOTA, HONDA, NISSAN, BMW, MERCEDES
}
как вы можете видеть, State
перечисление содержит все возможности Car
перечисления.
Итак, я хочу сделать что-то вроде этого:
public void sayHello(Car brand) {
State s = ... // how to convert the brand parameter into the corresponding State enum?
...
...
}
Итак, я хочу иметь возможность преобразовать данное Car
перечисление в State
enum в минимальном коде, который легко понять. Я знаю, что могу использовать переключатель, но это большая потеря кода. Поэтому, пожалуйста, помогите мне здесь.
Комментарии:
1. Просто для справки: принятый ответ работает, но имеет некоторые недостатки. Я не возражаю против принятия этого, но, пожалуйста, прочитайте мой комментарий там и содержимое, которое я добавил к своему ответу, чтобы получить полную картину.
Ответ №1:
Вы можете присвоить перечислению состояния закрытое поле типа Car. Затем вы добавляете частный конструктор, который принимает объект Car и сохраняет его в указанном поле. Затем вы можете объявить свои константы состояния, такие как
SOLD(null), BMW(Car.BMW),...
Но: концептуально это не имеет смысла. Автомобиль — это автомобиль, и, возможно, транзакция имеет два свойства state и car (когда состояние ПРОДАНО), но состояние не должно отражать тип автомобиля. Значение: что бы вы ни делали, чтобы получить Car enum из экземпляра State, ваша настоящая проблема заключается в вашем дизайне. Вы дублируете вещи, имея «одинаковые» константы уже в двух местах.
В вашем вопросе спрашивается, как наилучшим образом справиться с признаком плохого дизайна, и реальный ответ таков: вы этого не делаете. Вы исправляете дизайн вместо того, чтобы проклеивать реализацию.
Комментарии:
1. Спасибо GhostCat. Ваше решение тоже является допустимым, и ваши комментарии выше действительно имеют смысл, и я знаю о потенциальных недостатках решения @ernest_k, но это решение лучше подходит для того, что я искал.
Ответ №2:
Имея Car
значение, вы можете просто использовать поиск на основе имени:
public void sayHello(Car brand) {
State s = State.valueOf(brand.name());
...
}
Пока все Car
имена значений находятся в State
перечислении, это всегда должно работать.
Комментарии:
1. Это наверняка работает, но у него есть два недостатка: как вы сами сказали: это заставляет вас вручную синхронизировать два перечисления. Если вы добавляете новый Car, но забываете о состоянии, этот код генерируется во время выполнения. Такой подход убивает проверку во время компиляции. Тогда вы могли бы также прибегнуть к плоским строкам! Плюс: это решение дополнительно демонстрирует лежащий в его основе плохой дизайн . Это усугубляет ситуацию, и со временем будет появляться все больше плохих пластырей.
2. Итак, минимум , что вам следует сделать здесь, — это провести модульный тест в классе State, который повторяет все экземпляры Car и гарантирует, что сопоставление с State работает. В противном случае одной опечатки будет достаточно, чтобы ваш код позже вышел из строя!
3. @GhostCat Это верно. Это решение для преобразования
String
вenum
. Конечно, я рассчитывал на предположение OP о том, что «перечисление состояний содержит все возможности перечисления Car», и могу только предположить, что это проверено. Я понимаю, к чему вы клоните. Но мы все знаем, что бывают случаи, когда тип связи, который вы предлагаете, является плохой идеей (или просто неосуществимой). Не говорю, что ваше решение неверно, но что оно имеет свое место, точно так же, как оригинальный дизайн OP тоже имеет свое место.4. Как я сказал op: просто хотел, чтобы он знал об этих вещах. Мне все равно, куда идут акцепты, главное, чтобы они шли куда-нибудь разумно 🙂