JEP 301: Enhanced Enums

Maurizio Cimadamore maurizio.cimadamore at oracle.com
Thu Dec 8 00:10:03 UTC 2016



On 07/12/16 22:28, forax at univ-mlv.fr wrote:
>> De: "Maurizio Cimadamore" <maurizio.cimadamore at oracle.com>
>> À: "Remi Forax" <forax at univ-mlv.fr>, platform-jep-discuss at openjdk.java.net
>> Envoyé: Mercredi 7 Décembre 2016 10:48:44
>> Objet: Re: JEP 301: Enhanced Enums
>> Thanks for the feedback. I personally run into the lack of sharp typing
>> several times and seen other people stumbling on it too.
>>
>> Do you have some example in mind that will break - other than the ones
>> listed in the JEP? In my mental model, the kind of surprises this
>> introduces are very similar to anonymous inner class types - that is:
>>
>> new Object() { void m() { } }.m();
>>
>> this is legal code because the receiver expression doesn't have type
>> Object - but has a sharper type (which can 'see' the additional member).
>> This proposal is about doing the same with enums - which accidentally
>> will sit well with adding generics (because in that case, the constants
>> will have a richer generic type than their parent).
>
> Abstract enum where introduces as a kind of strawman lambdas (see [1]),
> and as Stephen said there were intentionally restricted to not be more than that.
The video you quote talks about enums inheritance - this JEP in no way 
affects the way in which enum can (or rather can't) subclass each other 
(and in fact this is even called out in the JEP). For illustrating the 
problem this JEP addresses, you don't need fancy hierarchies - all it 
takes is something simple like this:

enum Foo {
    A() { void a() { ... } },
    B,
    C() { void c() { ... } };

    void m() { ... }
}

Here we have three constants - they all have a method m() - one constant 
(A) has a method a() and another constant (C) has a method c().

This is not some theoretical example - think of an enum modelling e.g. 
JVM primitive types - it's not that unreasonable to have operation on 
certain types but not on others - for instance you can do a conditional 
jump on an int ( 'if_icmp') - but you cannot do the same on floats 
(there's no 'if_fcmp'). Or maybe, some operation returns a result of one 
type in some case, but something of a different result in other cases - 
for instance, loading an int (iload) gives you an int - loading a float 
(fload) gives you a float.

Now, how do we implement these things if we want to use today's enums? 
One common (and ugly!) idiom seems to be this:

enum Foo {
    A,
    B,
    C;

    void m() { ... }

    void a() {
         switch (this) {
             case A: //do something
             default: throw
        }
    }

    void c() {
         switch (this) {
             case C: //do something
             default: throw
        }
    }
}

This has, IMO, several issues:

* encapsulation is broken - methods are not declared where they really 
belong
* no static safety - the compiler doesn't blink if you say Foo.B.c();
* readability - every method needs to be turned inside out into a switch

The goal of this JEP is to make stuff like this easier to write - and we 
want to be able to get there so that the extra typing information is 
there _if you need it_. If you don't care about the sharp types, fine - 
they won't harm you either (and for the most part you can pretend they 
don't even exist).

Maurizio
>
>> Maurizio
> Rémi
>
> [1] https://youtu.be/pi_I7oD_uGI?t=2041
>
>>
>> On 07/12/16 09:03, Remi Forax wrote:
>>> Now, If this proposal is accepted, at least, instead of changing the spec to
>>> introduce sharp types for all kind of enums, adding sharp type only for
>>> generics enums,
>>> it will break no code because generics enum currently do not compile.



More information about the platform-jep-discuss mailing list