7

I am curious to see any alternative(s) to the regular if statements such as

if(x)
     do a;
if(y)
     do b;
if(z)
    do c;

so as you see all if statements are seperate and no else condition. Please notice that X Y Z are totally seperate conditions so switch wouldn't fit.

Hellnar
  • 62,315
  • 79
  • 204
  • 279
  • 4
    While curiosity might be humorous ... why would I want an alternative to if, especially when a condition is that switch doesn't fit? As if Java wasn't bloated enough already... – ty812 Oct 25 '09 at 17:21
  • either what you are trying to do is silly (if's are great!), or you need to give more information. i can imagine a situation where code like this could be handled with a messaging pattern or something else that is interesting (provided that your situation is not as simple as you explained it). – twolfe18 Oct 25 '09 at 17:23
  • What do you expect this alternative to provide that the presented code cannot? (less characters, more readability?) – Zed Oct 25 '09 at 17:25
  • well I am just exploring, I know "if"statement is elegant and easy to read but extra knowledge never hurts :) – Hellnar Oct 25 '09 at 17:26
  • 3
    @Hellnar: There's extra knowledge that has value, and there's obscure code golf junk. – S.Lott Oct 25 '09 at 17:28
  • 2
    in large enough quantity, `if` statements are poisonous – Alex R Nov 13 '13 at 01:34

11 Answers11

32

One "truely object oriented" answer would be to define an interface for "Rule" (with condition() and action() methods), create 3 implementations, stuff them into a collection, and then just iterate through them generically as in:

List<Rule> rules = .... ; // your 3 rules initialized here somehow
for(Rule r : rules) {
  if(r.condition()) {
    r.action();
  }
}

This makes a lot more sense if you have 300 rules/conditions rather than just 3.

In Java8, you may want to do this instead, if the rules are CPU-intensive:

rules.parallelStream().filter(Rule::condition).forEach(Rule::action);
Alex R
  • 11,364
  • 15
  • 100
  • 180
  • You could use a Map for O(1) time, rather than O(n). – Dave Jarvis Jun 10 '13 at 16:05
  • A Map won't work here, because the condition is unique to each Rule implementation. Map requires an actual key, not some code buried in a callable method. – Alex R Oct 26 '13 at 00:23
9

The short answer is yes.

There are a few time you can avoid using if for conditional evluation and branching all together. And they have moments of appropriateness.

  1. Polymorphism, when behavior is dependent on the initial values
  2. Referrenced Assignment, when you know the possible initial values and they have 1 to 1 correlation with the return values. Lists are better than arrays for this, but...

    // Example:  
    if (a==1) { b=2;  }  
    if (a==2) { b=17; }  
    
    // Becomes  
    int fx(2);  // our array of answers  
    fx[0] = 2;   
    fx[1] = 17;  
    b = fx[ a - 1 ];
    
  3. Referrenced Branching, when you know the possible initial values and they have 1 to 1 correlation with the function/branch to use. (example not Java)

    // Example:
    if (a==1) { doSomething1();  }  
    if (a==2) { doSomething2(); }  
    
    // Becomes
    function * fx(2);  // our array or better still, list of functions  
    fx[0] = &doSomething1;   
    fx[1] = &doSomething2;  
    `fx[ a - 1 ](); `
    
  4. Direct boolean assignment.

    We hate:

    if (thisCondition == true) {  
      b = true;  
    } else {  
      b = false;  
    }
    

    Should be:

    b = thisCondition;

Ould Abba
  • 813
  • 1
  • 12
  • 25
Bill Bingham
  • 244
  • 1
  • 3
6

The alternatives to if-else in Java are the switch statement and the conditional ternary (?:) operator, neither of which do exactly what you're asking (handle just an if with no else). The code you posted is the best way to do it, in my opinion.

Bill the Lizard
  • 398,270
  • 210
  • 566
  • 880
  • Multiple conditions in Ternary : https://stackoverflow.com/questions/12548857/multiple-conditions-in-ternary-conditional-operator – Vacca Mar 20 '19 at 10:10
4

Use polymorphism.

interface SomethingDoer {
    public void doSomething();
}

class ADoer implements SomethingDoer { ... }
class BDoer implements SomethingDoer { ... }
class CDoer implements SomethingDoer { ... }

public class Main {
     public static void main (String[] args) {
          SomethingDoer doer = new SomethingDoerFactory(args).getDoer();
          doer.doSomething();
     }
}

The if is not completely eliminated, but it is moved to SomethingDoerFactory. This solution is not applicable in all cases, but in some of them it is a very good alternative to multiple ifs.

Here is a nice talk about it:
http://misko.hevery.com/2008/12/08/clean-code-talks-inheritance-polymorphism-testing/

artemb
  • 9,251
  • 9
  • 48
  • 68
  • 1
    Any comments on why you downvote? Isn't it an alternative? Or isn't it good enough to be mentioned? – artemb Oct 25 '09 at 17:33
  • 3
    I'd only consider a polymorphic solution if my conditional was already based on **type**. I wouldn't create an entire class hierarchy just to replace `if(x) do a;` – Bill the Lizard Oct 25 '09 at 17:48
  • 2
    if many cases this makes sense. see http://www.youtube.com/watch?v=4F72VULWFvc - google tech talks. (The Clean Code Talks -- Inheritance, Polymorphism, & Testing) i consider the downvote wrong. – Andreas Petersson Oct 25 '09 at 17:59
  • 1
    Direct from Misko's slides: "sometimes an if is just an if". Unless you re-use these if statements in a lot of places, this is going to make things needlessly complex. Also: your solution is incomplete. What if both conditions x and y hold? You have missed AAndBDoer, AAndCDoer, BAndCDoer, AAndBAndCDoer; these are well-covered by the original code. – Zac Thompson Oct 25 '09 at 18:40
  • Obviously this depends on exactly what it means to "do a". Polymorphism might well be an excellent solution, but the example is simply too generic to have a single solution for all cases. AAndBDoer etc are typically solved by using Decorator/Composition patterns for a polymorphism-type solution. – Eek Oct 25 '09 at 23:17
3

this is the most simple, readable yet effective solution. I would be surprised to see effective alternatives here.

EDIT

you can try to apply extract method several times:

doAIfX();
doBIfY();
doCifZ();

where methods are defined by:

void doAIfX() {
    if (!X) {
        return;
    }

    // do 'a'
}
dfa
  • 114,442
  • 31
  • 189
  • 228
  • I do this in firmware for a device that can have many different options enabled or disabled. I'd rather have my main() call things like doFooIfEnabled() than clutter it up with lots of ifs and #ifdefs. – Jeanne Pindar Oct 25 '09 at 18:35
  • 1
    Like any pattern, there are times when it should be used, and times when it shouldn't. – bdonlan Oct 25 '09 at 18:51
2

Do something like this, Implement Enum based on condition and call override method.

public enum Rule{
            a(){
            @Override
            public void do(){
            // do something.
            }
            },
            b(){
            @Override
            public void do(){
            // do something.
            }
            },
            c(){
            @Override
            public void do(){
            // do something.
            }


            public abstract void do();

            }
        }




     public class Test{
            public static void main(String[] args){
                Rule r = Rule.valueOf("a");
                r.do();
            }
        }
Piyush Ghediya
  • 1,754
  • 1
  • 14
  • 17
0

How about... myAnimator(thing, pos, speed | computeSpeed());

if speed === undefined it will then computeSpeed... I think.

MistereeDevlord
  • 876
  • 7
  • 10
0

it really depends on what x, y, z and a, b, c are. Sometimes if statements are more suitable. Sometimes polymorphism is more suitable.

Nat
  • 9,820
  • 3
  • 31
  • 33
0

You will need to have these if statements somewhere.

They can be refactored into other methods to keep the present method clean, as others have suggested. If you need to re-use this same set of if statements in a number of places, it might be possible use the Decorator Pattern.

Zac Thompson
  • 12,401
  • 45
  • 57
0

It sounds like a perfect case for using closure. But for that you need groovy or something similar.

fastcodejava
  • 39,895
  • 28
  • 133
  • 186
0

It's really depends on the context... but yeah if-else is only one of control flow statement in java: https://docs.oracle.com/javase/tutorial/java/nutsandbolts/flow.html

HoaPhan
  • 1,714
  • 1
  • 13
  • 35