6

Suppose I want to create a set of related functions and want to group them in an enum.

I can code, just for example:

enum Case implements Function<Object, String> {
    UPPER {
        public String apply(Object o) {
            return o.toString().toUpperCase();
        }
    },
    LOWER {
        public String apply(Object o) {
            return o.toString().toLowerCase();
        }
    }
}

I would like to be able to code this as a lambda, something like (but doesn't compile):

enum CaseLambda implements Function<Object, String> {
    UPPER (o -> o.toString().toUpperCase()),
    LOWER (o -> o.toString().toLowerCase())
}

I've tried a few variations of brackets etc, but nothing compiles.

Is there a syntax that allows the declaration of enum instance implementation as lambda?

Pshemo
  • 122,468
  • 25
  • 185
  • 269
Bohemian
  • 412,405
  • 93
  • 575
  • 722
  • I'm curious what the compilation error is. – Radiodef Oct 31 '14 at 00:26
  • 5
    Would it work for you to declare a `Function` field in the enum, pass it into the constructor, and call the constructors as in your second snippet? Or is that too much boilerplate? – yshavit Oct 31 '14 at 00:26
  • @yshavit That is what I assumed he was trying to do in the 2nd snippet. (Maybe my assumption was wrong though.) – Radiodef Oct 31 '14 at 00:28
  • 1
    There's not nearly as much _point_ to wrapping your `Function`s in enums in Java 8. The implementation is smart enough to extract a singleton lambda, rather than regenerating it each time it's referenced, so you might as well just insert the lambdas directly into the places you use them. – Louis Wasserman Oct 31 '14 at 01:35
  • 2
    @LouisWasserman but I want the benefits of using an enum to show the developer the list of functions that make sense (ie strongly type a set of supported functionality), and I'm also iterating over them and applying all functions in a particular case. – Bohemian Oct 31 '14 at 02:08

1 Answers1

15

No, the enum constant syntax does not allow it. If you declare a constant with a body, that body is a classbody.

yshavit's suggestion seems appropriate. Delegate to the Function implementation.

enum Case implements Function<Object, String> {
    UPPER (o -> o.toString().toUpperCase()),
    LOWER (o -> o.toString().toLowerCase());

    private final Function<Object, String> func;

    private Case(Function<Object, String> func) {
        this.func = func;
    }

    @Override
    public String apply(Object t) {
        return func.apply(t);
    }
}
Community
  • 1
  • 1
Sotirios Delimanolis
  • 274,122
  • 60
  • 696
  • 724
  • 1
    Close enough - I'll take it as a win! Not too much boiler plate, because at least it doesn't repeat the boilerplate. If there are many instances, the brevity will be welcome. – Bohemian Oct 31 '14 at 00:33
  • 2
    Note that some aspects of this pattern have been already discussed in [this question](http://stackoverflow.com/q/23361418/2711488)… – Holger Oct 31 '14 at 09:14