views:

106

answers:

5

The following code does not compile because eater is defined twice:

switch (vegetable) {
    case TOMATO:
        Eater eater = new Eater(Tomato.class, many parameters);
        eater.eat(more parameters);
        return true;

    case POTATO:
        Eater eater = new Eater(Potato.class, many parameters);
        eater.eat(more parameters);
        return true;

    case CARROT:
        doSomethingElse();
        return true;
}

Should I:

  • Use separate variables `tomatoEater` and `potatoEater`, making the code less maintainable?
  • Define `eater` before the `switch`, making it accessible to more than it should?
  • Define `eater` the first time only, leading to potential confusion?
  • Add braces, making the code more verbose?
  • Any better idea?
+5  A: 

I would personally either use braces, or just abandon the local variable completely:

new Eater(Potato.class, many parameters)
     .eat(more parameters);

The disadvantage of this is that it makes it a little harder to debug. Obviously this isn't your real code though... which makes it hard to say the right thing to do. It's quite possible that the right thing to do is actually to break out the bodies of the cases into separate methods.

Jon Skeet
Beat me to it...
Nivas
Extract Method IS your friend.
mjfgates
@mjfgates: Not always. Take each case as it comes. For a two-liner, I think I'd often rather go with extra braces. In many other cases though, I agree.
Jon Skeet
+2  A: 

Why not this:

switch (vegetable) 
{ 
    case TOMATO: 
        new Eater(Tomato.class, many parameters).eat(more parameters); 
        return true; 

    case POTATO: 
        new Eater(Potato.class, many parameters).eat(more parameters); 
        return true; 

    case CARROT: 
        doSomethingElse(); 
        return true; 
} 

If you dont have any use of the Eater reference anywhere else later, I would do this.

Nivas
A: 

How would using separate variables make the code less maintainable? (first bullet point). If anything I would say it would do the opposite as the variable name better explains what it is. I would go with that if keeping it in that scope is important to you.

Joel
The more each case is similar, the easiest it is to copy-paste to create a new case, or refactor. Let's say I want to add a `eater.init()` after each creation, it will be painful if I have to adapt the variable name for each case. I avoid creating many variable names if there is no good reason. And also, it takes a bit more memory if not used with braces.
Nicolas Raoul
+1  A: 

Not quite the same logic as your method (carrot is treated as default) but shows an alternative approach (with some more behind the scenes wiring that I haven't worried about here):

Eater eater = vegetable.getEater(many parameters);
if (eater != null) eater.eat(more parameters);
else doSomethingElse();
return true;
CurtainDog
A: 

Maybe using a switch isn't such a good idea at all.


In what better example can represent a switch statement in Java ?

Colin Hebert