dada dudu
dada dudu

Reputation: 129

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. The problem is that I've multiple arguments, so I don't know how to handle that.

Here are my if-else's:

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();
        }

Upvotes: 1

Views: 369

Answers (3)

GhostCat
GhostCat

Reputation: 140427

You might step back for a second and read about the TDA principle.

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. Instead: you create proper OO abstractions; and use factories and polymorphism. And let me be very clear about this: switch statements are not the answer to your problems. They are just a syntactically-marginally-improved version of if/else trees.

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! 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!

Upvotes: 3

Jaroslaw Pawlak
Jaroslaw Pawlak

Reputation: 5578

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;
}

Upvotes: 0

Fitzwilliam Bennet-Darcy
Fitzwilliam Bennet-Darcy

Reputation: 1342

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.

Upvotes: 3

Related Questions