简体   繁体   English

if-else和switch语句的替代方案

[英]Alternative of if-else and switch statements

I have the following code in Java: 我在Java中有以下代码:

public void doSomething(int i) {
    if (i == 12) {
        // order should be same
        up();
        left();
        stop();
    }
    if (i == 304) {
        // order should be same
        right();
        up();
        stop();
    }
    if (i == 962) {
        // order should be same
        down();
        left();
        up();
        stop();
    }
}
// similar code can be done using switch case statements.
// all the function can have any functionality and might not resemble to the name given to them.

Now if I am asked not to use either of if-else and switch case statements, then what can be done? 现在,如果我被要求不使用if-else和switch case语句,那么可以做些什么呢? The code can be done in either Java or JavaScript. 代码可以用Java或JavaScript完成。

If you can use JavaScript, you can use a object with functions: 如果您可以使用JavaScript,则可以使用具有以下功能的对象:

function doSomething(i) {
  var obj = {};

  obj[12] = function () {
    // order should be same
    up();
    left();
    stop();
  };
  obj[304] = function () {
    // order should be same
    right();
    up();
    stop();
  };
  obj[962] = function () {
    // order should be same
    down();
    left();
    up();
    stop();
  };

  // apparently we can't use any conditional statements
  try {
    obj[i]();
  } catch (e) {}
}

If only if and switch statements aren't allowed, replace all the if statements with the logical AND operator ( && ): 如果仅ifswitch语句, if用逻辑AND运算符( && )替换所有if语句:

function doSomething(i) {
  (i == 12) && (
    // order should be same
    up(),
    left(),
    stop()
  );

  (i == 304) && (
    // order should be same
    right(),
    up(),
    stop()
  );

  (i == 962) && (
    // order should be same
    down(),
    left(),
    up(),
    stop()
  );
}

Here is a simple way to accomplish this in JavaScript: 以下是在JavaScript中完成此操作的简单方法:

function up()    { console.log("up");    }
function down()  { console.log("down");  }
function left()  { console.log("left");  }
function right() { console.log("right"); }
function stop()  { console.log("stop");  }

var fnmaps = {
    12:  [up, left, stop],
    304: [right, up, stop],
    962: [down, left, up, stop]
};

function doSomething(i) {
    var fnmap = fnmaps[i] || [], j;
    for (j = 0; j < fnmap.length; j++) {
        fnmap[j]();
    }
}

doSomething(12);
doSomething(304);
doSomething(962);

Functions can be added/ordered simply by editing the map variable. 只需编辑map变量即可添加/排序函数。

You can make a dictionary of input-to-action. 您可以制作输入操作的字典。 In Java this would be a Map<Integer, Runnable> , with, for instance*: 在Java中,这将是Map<Integer, Runnable> ,例如*:

map.put(12, () -> {
    up();
    left();
    stop();
});

Then, you can get the appropriate Runnable and run it: 然后,您可以获取相应的Runnable并运行它:

Runnable action = map.get(i);
if (action != null) {
    action.run();
} else {
    // some default action
    // This is the "default" case in a switch, or the "else" in an if-else
}

The if-else there isn't strictly necessary, but without it, you'll get a NullPointerException if i isn't an expected value — that is, one of the values you put into the map. if-else并不是绝对必要的,但如果没有它,如果i不是一个期望的值,你将得到一个NullPointerException - 也就是你放入地图的值之一。

The idea is similar in JavaScript, though with objects instead of Map s, functions (probably anonymous) instead of Runnable s, etc. 这个想法在JavaScript中类似,但是使用对象而不是Map ,函数(可能是匿名的)而不是Runnable等。


This code is for Java 8. In Java 7 and below, you'd do: 此代码适用于Java 8.在Java 7及更低版本中,您将执行以下操作:

map.put(12, new Runnable() {
    @Override
    public void run() {
        up();
        left();
        stop();
    }
});

Wahahahahaha, you saved my day :) This should work, no way to test right now.. 娃哈哈哈哈,你救了我的一天:)这应该工作,现在没办法测试..

public void doSomething(int i) {

try {
    int x = 1/(12-i); // fails for i==12
} catch (ArithmeticException e) {
        up();
        left();
        stop();
}

and so on, enjoy! 等等,享受!

Then do it with while and break, there is no other way without condition check 然后用while和break来做,没有其他方法没有条件检查

public void doSomething(int i) {

while(i == 12) {
// order should be same
    up();
    left();
    stop();
break;
    }

while(i == 304) {
// order should be same
    right();
    up();
    stop();
break;
    }

while(i == 962) {
// order should be same
    down();
    left();
    up();
    stop();
break;
    }
}

Look, naturally you should inspect a conditional statement with a conditional expression! 看, 自然你应该用条件表达式检查一个条件语句! Now, if you don't want to do this, you can do it unnaturally like this: 现在,如果你不想这样做,你可以不自然地这样做:

first do this for all methods (up,down,...) 首先为所有方法执行此操作(向上,向下,...)

java.lang.reflect.Method method;
try {
  method = obj.getClass().getMethod(methodName, param1.class, param2.class, ..);
} catch (SecurityException e) {
  // ...
} catch (NoSuchMethodException e) {
  // ...
}

instead of an integer that you pass to the doSomething , use an array containing name of the methods that you want to call and inside a for loop call each method this way: 而不是传递给doSomething的整数,使用包含要调用的方法的名称的数组,并在for循环内调用每个方法:

Then you invoke that method by calling 然后通过调用调用该方法

try {
  method.invoke(obj, arg1, arg2,...);
} catch (IllegalArgumentException e) {
} catch (IllegalAccessException e) {
} catch (InvocationTargetException e) {

Unfortunately Java has not delegates ! 不幸的是,Java没有代表

for js u may try this: 对于js你可以试试这个:

// define ur actions here
var actions = {
  "12" : function () { up(); left(); stop(); },
  "304" : function () { right(); up(); stop(); },
  "962" : function () { down(); left(); up(); stop(); }
};

function doSomething(i) {
  var fn = actions[i];
  try {
    fn();
  } catch (err) {
    console.error(err);
  }
}
//
doSomething(12); //invoke here

This problem could be solved using OOP techniques. 使用OOP技术可以解决这个问题。

In java it would look like this: 在java中它看起来像这样:

public abstract class AObject{
   public abstract  void doSomething();
   public void  up(){
      //do something here
   }
   public void down(){
      //do something here
   }
   public void left(){
      //do something here
   }
   public void right(){
      //do something here
   }       
   public void stop(){
      //do something here
   }     
}


public class AObject12 extends AObject{
   public void doSomething(){
      up();
      left();
      stop();
   }
}

public class AObject304 extends AObject{
   public void doSomething(){
      right();
      up();
      stop();
   }
}

public class AObject962 extends AObject{
   public void doSomething(){
      down();
      left();
      up();
      stop();
   }
}

Executing doSomething on a instance of a concrete class will trigger the appropriate behavior. 在具体类的实例上执行doSomething将触发相应的行为。 So no more if/else is necesary. 如果/其他是必要的,那就不多了。 See code below for an example: 请参阅下面的代码示例:

AObject A12 = new AObject12();
A12.doSomething();
// Will run Up left stop in that order

AObject A304 = new AObject304();
A304.doSomething();
// Will run right Up stop in that order

AObject A962 = new AObject962();
A962.doSomething();
// Will run down left up stop in that order

Some more info on this kind of programming can be found here: http://en.wikipedia.org/wiki/Polymorphism_%28computer_science%29 有关此类编程的更多信息,请访问: http//en.wikipedia.org/wiki/Polymorphism_%28computer_science%29

If you would like to be able to change the behavior of the object dynamicly you could consider applying a state pattern: http://en.wikipedia.org/wiki/State_pattern 如果您希望能够动态地更改对象的行为,可以考虑应用状态模式: http//en.wikipedia.org/wiki/State_pattern

In Java, this should work.. 在Java中,这应该工作..

public class IfTest {

    public static void main(String[] args) {
        IfTest ifTest = new IfTest();

        ifTest.doSomething(12);
        ifTest.doSomeThingWithoutIf(12);

        ifTest.doSomething(304);
        ifTest.doSomeThingWithoutIf(304);

        ifTest.doSomething(962);
        ifTest.doSomeThingWithoutIf(962);

        ifTest.doSomething(42);
        ifTest.doSomeThingWithoutIf(42);
    }

    public void doSomeThingWithoutIf(int i) {


        boolean x = i == 12 ? f12() : (i == 304 ? f304() : (i == 962 ? f962() : false));
    }

    public boolean f12() {

        up();
        left();
        stop();

        return true;
    }

    public boolean f304() {

        right();
        up();
        stop();
        return true;
    }

    public boolean f962() {

        down();
        left();
        up();
        stop();

        return true;
    }

    public void doSomething(int i) {

        if(i == 12) {
            // order should be same
            up();
            left();
            stop();
        }

        if(i == 304) {
            // order should be same
            right();
            up();
            stop();
        }

        if(i == 962) {
            // order should be same
            down();
            left();
            up();
            stop();
        }
    }

    private boolean retfalse() {
        return false;
    }

    private void down() {
        System.out.println("down");
    }

    private void right() {
        System.out.println("right");
    }

    private void stop() {
        System.out.println("stop");
    }

    private void left() {
        System.out.println("left");
    }

    private void up() {
        System.out.println("up");
    }
}

The desired behavior can be achieved in JAVA by playing with the short-circuit of the logical AND operator as follows: 通过播放逻辑AND运算符的短路,可以在JAVA中实现所需的行为,如下所示:

public static Boolean seq12() {
    // order should be same
    up();
    left();
    stop();
    return true;
}
public static Boolean seq304() {
    // order should be same
    right();
    up();
    stop();
    return true;
}
public static Boolean seq962() {
    // order should be same
    down();
    left();
    up();
    stop();
    return true;
}

public static void doSomething(int i) {
    Boolean tmp;
    tmp = (i == 12 && seq12());
    tmp = (i == 304 && seq304());
    tmp = (i == 962 && seq962());
}

This code is pretty straight-forward and relies on the fact that the logical AND operator only evaluates the second operand if the first one is true . 这段代码非常简单,并且依赖于逻辑AND运算符仅在第一个操作数为时才计算第二个操作数的事实

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM