1

I have two enums in two different classes (shown below):

enum State {
 NOCAR, SOLD, TO_BUY, TOYOTA, HONDA, NISSAN, BMW, MERCEDES, NO_MONEY
}

enum Car {
 TOYOTA, HONDA, NISSAN, BMW, MERCEDES
}

as you can see that the State enum contains all the possiblities of the Car enum.

So I want to do something like this:

public void sayHello(Car brand) {
  State s = ... // how to convert the brand parameter into the corresponding State enum?
  ...
  ...
}

So I want to be able to convert a given Car enum into a State enum in minimal code that is easy to understand. I know I can use a switch but that is a lot of code wastage. So please help me here.

1
  • Just for the record: the accepted answer works, but has some drawbacks. I don't mind the accept on it, but please read my comment there, and the content I added to my answer to get a complete picture. Commented Mar 23, 2019 at 5:34

2 Answers 2

4

You can give the State enum a private field of type Car. Next, you add a private constructor that takes a Car object, and stores that in said field. Then you can declare your State constants like

SOLD(null), BMW(Car.BMW),...

But: conceptually, this doesn't make sense. A Car is a Car, and maybe a transaction has two properties state and car (when the state is SOLD), but the state should not reflect a car type. Meaning: whatever you do to get a Car enum from a State instance, your real problem is your design. You are duplicating things by having the "same" constants in two places already.

Your question asks how to best deal with a symptom of bad design, and the real answer is: you don't. You fix the design instead of duct taping the implementation.

Sign up to request clarification or add additional context in comments.

1 Comment

Thanks GhostCat. Your solution is a valid one too and your comments above do make sense and I am aware of the potential disadvantages of @ernest_k's solution but that solution suits better what I was looking for.
3

Having a Car value, you can just use a name-based lookup:

public void sayHello(Car brand) {
  State s = State.valueOf(brand.name());
  ...
}

As long as all Car value names are in the State enum, this should always work.

4 Comments

This for sure works, but it has two disadvantages: as you said yourself : it forces you to manually keep the two enums to be in sync. If you add a new Car, but forget about the State, this code throws at runtime. This approach kills compile time checking. You could as well resort to flat strings then! Plus: this solution further manifests the underlying bad design. It makes things worse, and over time, more bad Band aids will come in.
So the minimum that you should do here is to have a unit test in the State class that iterates all Car instances and ensures the mapping to State works. Otherwise one typo is enough to crash your code later!
@GhostCat That's right. This is a String to enum conversion solution. Of course, I counted on the OP's assumption that "the State enum contains all the possiblities of the Car enum" and can only suppose this is tested. I see the point you're making. But we all know that there are cases where the kind of coupling you're suggesting is a bad idea (or plain infeasible). Not saying your solution is wrong, but that it has its place, just as the OP's original design has its place too.
As I told the op: just wanted to make him aware of these things. I don't care where accepts go, as long as they go somewhere reasonable :-)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.