Java switch-setning med flere tilfeller

Bare prøver å finne ut hvordan du bruker mange flere tilfeller for en Java-setning. Her er et eksempel på hva jeg prøver å gjøre:

switch (variable)
{
    case 5..100:
        doSomething();
    break;
}

kontra å måtte gjøre det:

switch (variable)
{
    case 5:
    case 6:
    etc.
    case 100:
        doSomething();
    break;
}

Noen ideer om dette er mulig, eller hva et godt alternativ er?

Løsning

Dessverre er det ikke mulig i Java. Du må ty til if-else-setninger.

Kommentarer (16)

Det andre alternativet er helt greit. Jeg er ikke sikker på hvorfor en av respondentene sa at det ikke var mulig. Det går helt fint, og jeg gjør det hele tiden:

switch (variable)
{
    case 5:
    case 6:
    etc.
    case 100:
        doSomething();
    break;
}
Kommentarer (6)

Et objektorientert alternativ for å erstatte overdrevent store switch- og if/else-konstruksjoner er å bruke et Chain of Responsibility Pattern for å modellere beslutningsprosessen.

**Mønster for ansvarskjede

Ansvarskjedemønsteret gjør det mulig å skille mellom kilden til en forespørsel fra beslutningen om hvilken av de potensielt mange et potensielt stort antall behandlere som skal som skal behandle forespørselen. Klassen klassen som representerer kjederollen kanaliserer forespørslene fra kilden langs listen over behandlere helt til en håndterer aksepterer forespørselen og behandler den.

Her er et eksempel på en implementering som også er typesikker ved hjelp av Generics.

import java.util.ArrayList;
import java.util.List;

/**
* Generic enabled Object Oriented Switch/Case construct
* @param  type to switch on
*/
public class Switch
{
    private final List cases;

    public Switch()
    {
        this.cases = new ArrayList();
    }

    /**
     * Register the Cases with the Switch
     * @param c case to register
     */
    public void register(final Case c) { this.cases.add(c); }

    /**
     * Run the switch logic on some input
     * @param type input to Switch on
     */
    public void evaluate(final T type)
    {
        for (final Case c : this.cases)
        {
            if (c.of(type)) { break; }
        }
    }

    /**
     * Generic Case condition
     * @param  type to accept
     */
    public static interface Case
    {
        public boolean of(final T type);
    }

    public static abstract class AbstractCase implements Case
    {
        protected final boolean breakOnCompletion;

        protected AbstractCase()
        {
            this(true);
        }

        protected AbstractCase(final boolean breakOnCompletion)
        {
            this.breakOnCompletion = breakOnCompletion;
        }
    }

    /**
     * Example of standard "equals" case condition
     * @param  type to accept
     */
    public static abstract class EqualsCase extends AbstractCase
    {
        private final T type;

        public EqualsCase(final T type)
        {
            super();
            this.type = type;
        }

        public EqualsCase(final T type, final boolean breakOnCompletion)
        {
            super(breakOnCompletion);
            this.type = type;
        }
    }

    /**
     * Concrete example of an advanced Case conditional to match a Range of values
     * @param  type of input
     */
    public static abstract class InRangeCase extends AbstractCase
    {
        private final static int GREATER_THAN = 1;
        private final static int EQUALS = 0;
        private final static int LESS_THAN = -1;
        protected final T start;
        protected final T end;

        public InRangeCase(final T start, final T end)
        {
            this.start = start;
            this.end = end;
        }

        public InRangeCase(final T start, final T end, final boolean breakOnCompletion)
        {
            super(breakOnCompletion);
            this.start = start;
            this.end = end;
        }

        private boolean inRange(final T type)
        {
            return (type.compareTo(this.start) == EQUALS || type.compareTo(this.start) == GREATER_THAN) &&
                    (type.compareTo(this.end) == EQUALS || type.compareTo(this.end) == LESS_THAN);
        }
    }

    /**
     * Show how to apply a Chain of Responsibility Pattern to implement a Switch/Case construct
     *
     * @param args command line arguments aren't used in this example
     */
    public static void main(final String[] args)
    {
        final Switch integerSwitch = new Switch();
        final Case case1 = new EqualsCase(1)
        {
            @Override
            public boolean of(final Integer type)
            {
                if (super.type.equals(type))
                {
                    System.out.format("Case %d, break = %s\n", type, super.breakOnCompletion);
                    return super.breakOnCompletion;
                }
                else
                {
                    return false;
                }
            }
        };
        integerSwitch.register(case1);
        // more instances for each matching pattern, granted this will get verbose with lots of options but is just
        // and example of how to do standard "switch/case" logic with this pattern.
        integerSwitch.evaluate(0);
        integerSwitch.evaluate(1);
        integerSwitch.evaluate(2);

        final Switch inRangeCaseSwitch = new Switch();
        final Case rangeCase = new InRangeCase(5, 100)
        {
            @Override
            public boolean of(final Integer type)
            {
                if (super.inRange(type))
                {
                    System.out.format("Case %s is between %s and %s, break = %s\n", type, this.start, this.end, super.breakOnCompletion);
                    return super.breakOnCompletion;
                }
                else
                {
                    return false;
                }
            }
        };
        inRangeCaseSwitch.register(rangeCase);
        // run some examples
        inRangeCaseSwitch.evaluate(0);
        inRangeCaseSwitch.evaluate(10);
        inRangeCaseSwitch.evaluate(200);

        // combining both types of Case implementations
        integerSwitch.register(rangeCase);
        integerSwitch.evaluate(1);
        integerSwitch.evaluate(10);

    }
}

Dette er bare en rask stråmann som jeg snekret sammen på noen få minutter. En mer sofistikert implementering kan gjøre det mulig å injisere et slags Command Pattern i Case-implementeringsinstansene for å gjøre det til en mer IoC-lignende call back.

En fin ting med denne tilnærmingen er at Switch/Case-setninger handler om sideeffekter, dette innkapsler sideeffektene i klasser slik at de kan administreres og gjenbrukes bedre, det ender opp med å være mer som mønstermatching i et funksjonelt språk, og det er ikke en dårlig ting.

Jeg vil legge ut eventuelle oppdateringer eller forbedringer av denne Gist på Github.

Kommentarer (1)