简体   繁体   English

如何使用带有多个参数的switch()?

[英]How to use switch() with multiple arguments?

I want to use switch instead of if-else as I've that it's better when there are many if-else. 我想使用switch而不是if-else,因为当有很多if-else时,它会更好。 The problem is that I've multiple arguments, so I don't know how to handle that. 问题是我有多个参数,所以我不知道该如何处理。

Here are my if-else's: 这是我的if-else:

if(frame.height()/2 + margin < pt.y){
            System.out.println("down");
            drone.getCommandManager().down(20).doFor(100);
            drone.getCommandManager().hover();
        }
        else if(frame.height()/2 - margin > pt.y){
            System.out.println("up");
            drone.getCommandManager().up(20).doFor(100);
            drone.getCommandManager().hover();
        }
        else if(frame.width()/2+margin < pt.x){
            drone.getCommandManager().spinRight(30).doFor(33);
            drone.getCommandManager().hover();
            System.out.println("RIGHT");

        }
        else if(frame.width()/2-margin > pt.x){
            drone.getCommandManager().spinLeft(30).doFor(33);
            drone.getCommandManager().hover();
            System.out.println("LEFT");
        }

        else if(frame.width()/2+margin > pt.x && frame.width()/2-margin<pt.x){
            System.out.println("GO");
            drone.getCommandManager().forward(30).doFor(time+2000);
            drone.getCommandManager().hover();
        }

        else{
            drone.getCommandManager().hover();
        }

You can't. 你不能

The labels in a switch must be compile time evaluable constant expressions, and must compare exactly with the thing being switched on. switch的标签必须是编译时可评估的常量表达式,并且必须与打开的对象进行精确比较。

You might step back for a second and read about the TDA principle. 您可能会退一步,然后阅读有关TDA原理的信息。

What you are doing here in essence is: query the state of something, and then make decisions on how something else should be reacting to that. 本质上,您在这里所做的是:查询某物的状态,然后决定其他物应如何对此作出反应。 Thing is - that is really not object-oriented thinking. 事情是-确实不是面向对象的思想。

You could instead go for: 您可以改为:

interface CommandManagerUpdater {
  void updateOnNewDirection(CommandManager);
}

enum Direction { UP, DOWN, ... };

class DirectionDetector {
   Direction getNewDirection(Frame, x, yz, whatever you need)

class CommandManagerUpdaterFactory {
  CommandManagerUpdater generateUpdaterFor(Direction newDirection) {

If you have the above means in place, you can write up the whole thing as: 如果您具备上述方法,则可以将整个内容写为:

Direction newDirection = someDetector.getNewDirection(...)
CommandManagerUpdater updater = theFactory.generateUpdaterFor(newDirection);
updater.updateOnNewDirection(commandManager);

Long story short: in OO programming, you should avoid this kind of if/else/switch statements. 长话短说:在OO编程中,应该避免这种if / else / switch语句。 Instead: you create proper OO abstractions; 相反,您可以创建适当的OO抽象; and use factories and polymorphism. 并使用工厂和多态性。 And let me be very clear about this: switch statements are not the answer to your problems. 让我对此非常清楚: switch语句不能解决您的问题。 They are just a syntactically-marginally-improved version of if/else trees. 它们只是if / else树的句法边缘改进版本。

Of course, in the end, you need to a switch on "direction". 当然,最后,您需要打开“方向”。 But: you hide that switch inside the factory. 但是:您将开关隐藏在工厂内部。 There should be as few places as possible concerned about knowing all the potential directions. 应该尽可能少地关注所有潜在的方向。

Finally: keep an eye on code duplication. 最后:关注代码重复。 Check out how many times you have that "hoover()" call in your code - most them could go away! 检查您的代码中有多少次“ hoover()”调用-大多数可以消失! You know, when you go "hoover" all the time, for each of your direction; 您知道,每时每刻都在“徘徊”,朝着每个方向前进; then you call write down that call once unconditionally , instead of repeating it n times in each of your branches! 然后您无条件调用一次该调用,而不是在每个分支中重复n次!

I fully agree with what Jägermeister said. 我完全同意贾格迈斯特所说的。 I think you should use proper OO principles to improve your code, but if you really wanted a switch... 我认为您应该使用适当的面向对象原则来改进您的代码,但是如果您真的想要切换...

You should convert the expressions you have into single values. 您应该将拥有的表达式转换为单个值。 You could use an enum like: 您可以使用如下枚举:

public enum Result {
    A, B, C, D, E, F
}

Of course you should give it meaningful names! 当然,您应该给它起有意义的名字!

Then you can have a method which converts the expression into result: 然后,您可以使用一种将表达式转换为结果的方法:

public Result calculateResult() {
    if (frame.height() / 2 + margin < pt.y) {
        return A;
    } else if (frame.height() / 2 - margin > pt.y) {
        return B;
    } else if (frame.width() / 2 + margin < pt.x) {
        return C;
    } else if (frame.width() / 2 - margin > pt.x) {
        return D;
    } else if (frame.width() / 2 + margin > pt.x && frame.width() / 2 - margin < pt.x) {
        return E;
    } else {
        return F;
    }
}

Which in the end you can use in the switch: 最后可以在交换机中使用哪一个:

switch (calculateResult()) {
    case A:
        System.out.println("down");
        drone.getCommandManager().down(20).doFor(100);
        drone.getCommandManager().hover();
        break;
    case B:
        System.out.println("up");
        drone.getCommandManager().up(20).doFor(100);
        drone.getCommandManager().hover();
        break;
    case C:
        drone.getCommandManager().spinRight(30).doFor(33);
        drone.getCommandManager().hover();
        System.out.println("RIGHT");
        break;
    case D:
        drone.getCommandManager().spinLeft(30).doFor(33);
        drone.getCommandManager().hover();
        System.out.println("LEFT");
        break;
    case E:
        System.out.println("GO");
        drone.getCommandManager().forward(30).doFor(time + 2000);
        drone.getCommandManager().hover();
        break;
    case F:
        drone.getCommandManager().hover();
        break;
}

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

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