0

I have this enum:

    public enum Operation {
        ADD {
            public double apply(double a, double b) {
                return a + b;
            }
        },
        SUBTRACT {
            public double apply(double a, double b) {
                return a - b;
            }
        }
        } ;

        public abstract double apply(double a, double b);
`}`

I want to instantiate this like:

Operation op=new Operation("+");
op.aply(2,3);//now use ADD

Is it possible to write a constructor with string parameter that tells to enum which operation to aply?

2
  • You're making the mistake of trying to treat enum elements as if they were just regular old objects. Enum constructors are implicitly private (and you can't redefine them as anything else). What you'd really need to do is something like Operation.ADD.apply(2, 3); Commented Aug 14, 2014 at 13:38
  • @JonK Adding a look up is sensible for example if you want to call this from a parser Commented Aug 14, 2014 at 13:55

5 Answers 5

4

You can define a public static method to get the correct operation based on a String:

public static Operation get(String input) {
    if(input.equals("+")) {
        return ADD;
    }
    if(input.equals("-")) {
        return SUBTRACT;
    }
    throw new IllegalArgumentException();
}

Then you would call it like:

Operation op = Operation.get("+");
op.apply(2, 3);
Sign up to request clarification or add additional context in comments.

1 Comment

You could also put a lookup method inside the enum to return the correct element based on the input, which would be a better design
2

Unfortunately, no. You can create a method with a String parameter that returns the specific Operation depending on what is the parameter. Example :

public enum Operation {
    ADD("+") {
        public double apply(double a, double b) {
            return a + b;
        }
    },
    SUBTRACT("-") {
        public double apply(double a, double b) {
            return a - b;
        }
    };

    private String operationChar;

    private Operation(String s) {
        this.operationChar = s;
    }

    public static Operation getOperation(String s) {
    for (Operation o : Operation.values()) {
            if (o.operationChar.equals(s))
                return o;
        }
        return null;
    }

    public abstract double apply(double a, double b);
}

You can get the instance like this :

Operation op = Operation.getOperation("+");
op.apply(2,3); // ADD will be used here

(You can use a char instead of a String, since most operations only have one char (1+1, 1-1, 1*1, 1/1))

2 Comments

I'd still go for a string instead of a char (eg what if I want to represent modulo by mod instead of %)
Yes, a String would be better in that case, I just think that using Strings with only one character is a bit weird.
1

You can try the following example.

It's a bit over-engineered (you could ditch the whole "+" or "-" and call elements by name) but it works.

public enum Operation {
    ADD("+") {
        public double apply(double a, double b) {
            return a + b;
        }
    },
    SUBTRACT("-") {
        public double apply(double a, double b) {
            return a - b;
        }
    };
    public abstract double apply(double a, double b);
    String type;
    Operation(String type) {
        this.type = type;
    }
    public String getType() {
        return type;
    }
    static Operation get(String type) {
        for (Operation o: Operation.values()) {
            if (o.getType().equals(type)) {
                return o;
            }
        }
        throw new NoSuchElementException();
    }
    public static void main(String[] args) throws Exception {
        System.out.println(Operation.get("+").apply(1, 2));
    }
}

Output

3.0

Comments

1

You can define a constructor in an enum, but you cannot use it outside of the enum definition. The available enum values are fixed at compile time and you can't create more at runtime by using new. If you want to look up the enum by symbol, you need to define a lookup in the code.

For example by switching on the symbol:

public enum Operation {

    ADD {/*...*/};

    // ...

    public static Operation forSymbol(String symbol) {
        switch(symbol) {
        case "+":
            return ADD;
        //...
        default:
            throw new IllegalArgumentException("Unsupported symbol: " + symbol);
        }
    }
}

Or by defining the symbol together with the enum, and using that in the look up:

public enum Operation {

    ADD("+") {/*...*/};

    private final String symbol;

    private Operation(String symbol) {
        this.symbol = symbol;
    }

    // ...

    public static Operation forSymbol(String symbol) {
        for (Operation operation : Operation.values()) {
            if (operation.symbol.equals(symbol)) return operation
        }
        throw new IllegalArgumentException("Unsupported symbol: " + symbol);
    }
}

4 Comments

@JonK Oops, that is what you get with typing an example without an IDE (or compiling). Will update. And I also used == instead of equals... I blame it on too much C# use
== is fine for enums because they're guaranteed to be singletons, so they will be referentially equal if you're looking at the same element.
@JonK Except I was doing == on the string (symbol)... As I said: I blame C#
Ah! I hadn't noticed that either to be honest
0

It is not possible, due to the fact that enums cannot have public constructors (more information in this question). To use an Operation you will have to manually tell the compiler which Operation to use. This can be done by:

Operation op = ADD;
double x = op.apply(2,3);

which uses ADD as the Operation.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.