Anonymous classes of enum constants and var
David Alayachew
davidalayachew at gmail.com
Wed Feb 21 18:59:28 UTC 2024
And minor correction/clarification/consolidation on the intent of anonymous
class.
In short, an anonymous class allows you to change the insides
(implementation) while leaving the outside (api) untouched. But due to the
rules of scoping and access permissions, if your anonymous class happens to
be in the same compilation unit or scope, then fellow members of that
compilation unit or scope have access to not just your api, BUT YOUR
IMPLEMENTATION. That is why anonymous classes can have their newly
introduced public methoss called, even they are effectively unreachable
from anywhere else besides the sane compilation unit or scope.
On Wed, Feb 21, 2024, 1:55 PM David Alayachew <davidalayachew at gmail.com>
wrote:
> Hold on, I thought this was the entire purpose of refactoring an enum into
> a class?
>
> If all of the values do NOT have the same method, then by definition, they
> are not of the same type. The nature of an anonymous class is to,
> effectively, announce that you are making a new type that, if they are in
> the same scope, can use these new things you are defining on the anonymous
> type. But, because it is anonymous, then by definition,they have no way to
> access this UNLESS THOSE WISHING TO ACCESS ARE IN THE SAME COMPILATION
> UNIT. This is scope access.
>
> I think you are complecting the scope access with what abilities the
> anonymous class grants you. The anonymous class does not have the ability
> to effectively add to its public api. The fact that you can add a public
> method to an anonymous class is a very sharp edge that cuts a lot of
> developers. Yes, you can put a public method there, but it is almost
> entirely redundant. You cannot reference that public method because the
> only way to reference that public method is by having the type name. Since
> it is anonymous, then by definition, you can't. You must associate that
> method to a named type (for example, an interface) in order to be able to
> use your new public method. But by that point, it's not your anonymous
> class that added to the public api, it's the interface. Very sharp edge
> that should be removed in my firm opinion.
>
> At best, anonymous classes can modify the implementation of its public
> api, potentially. However, being in the same compilation unit/scope allows
> you to view fields and methods that you add to that anonymous class.
>
> Let me know if that doesn't make sense. But by definition, the thing you
> are trying to do is not attainable by anonymous classes alone. It would
> require some other mechanism to be introduced or used to introduce your
> method name into scope. And at that point, it would not be the anonymous
> class making this possible.
>
> But maybe I am completely wrong. I spent a couple frustrated months trying
> to do exactly what you are doing. Maybe something was added in the past few
> releases that made this now possible.
>
> On Wed, Feb 21, 2024, 1:02 PM Red IO <redio.development at gmail.com> wrote:
>
>> This is nice and well. But it isn't the same thing. Sure this works well
>> if every varient does exactly the same thing. But say you have a enum
>> having varients that share a feature but have their own unique properties.
>> Like a rule set to initialize something and an associated constants or
>> operation that only makes sense for 1 varient. Currently you need to define
>> both public constants and public methods in the enum associating it with
>> the whole enum instead of the varient that works with it. In methods that
>> gets even worse as you need to provide a default operation that either does
>> nothing or throws for incompatible varients. By simply typing the enum
>> constant to the anonymous class this would become possible.
>>
>> Great regards
>> RedIODev
>>
>> On Wed, Feb 21, 2024, 14:49 David Alayachew <davidalayachew at gmail.com>
>> wrote:
>>
>>> Idk which is the right group, but I choose amber.
>>>
>>> I just want to add a couple of clarifications on the various different
>>> forms (I spend a LOT of my time woth enums).
>>>
>>>
>>> - You can use an abstract method like so. It has the benefit of
>>> forcing every enum value to provide their own implementation of the
>>> abstract method. Think of it like a switch with no default clause.
>>>
>>>
>>> enum Blah
>>> {
>>>
>>> VALUE1
>>> {
>>>
>>> void method()
>>> {
>>>
>>> println("blah");
>>>
>>> }
>>>
>>> },
>>> ;
>>>
>>> abstract void method();
>>>
>>> }
>>>
>>>
>>> - Alternatively, you can provide an implementation of the method.
>>> This is more like a switch with a default clause.
>>>
>>>
>>> enum Blah
>>> {
>>>
>>> VALUE1
>>> {
>>>
>>> void method()
>>> {
>>>
>>> println("blah");
>>>
>>> }
>>>
>>> },
>>> ;
>>>
>>> void method()
>>> {
>>>
>>> println("default");
>>>
>>> }
>>>
>>> }
>>>
>>>
>>> - And of course, you could model this externally via a switch case.
>>> Both of the above bullets are modelable as switch expressions (as explained
>>> already). The benefit is that they can keep the enum simple, but the cost
>>> is that you must explicitly know the implementation you want instead of
>>> having one provided for you.
>>>
>>>
>>>
>>>
>>> On Wed, Feb 21, 2024, 7:14 AM Pavel Rappo <pavel.rappo at oracle.com>
>>> wrote:
>>>
>>>> From https://mail.openjdk.org/mailman/listinfo/discuss, this mailing
>>>> list is not suitable for questions like this. I'm not sure which mailing
>>>> list is *the most* suitable, but the following one is surely more suitable:
>>>> https://mail.openjdk.org/pipermail/amber-dev/ (CC'ed).
>>>>
>>>> I believe, the reasons why the first snippet of yours works, but the
>>>> second doesn't, is covered here:
>>>>
>>>> *
>>>> https://docs.oracle.com/javase/specs/jls/se21/html/jls-8.html#jls-8.9.1
>>>> (like you said)
>>>> *
>>>> https://docs.oracle.com/javase/specs/jls/se21/html/jls-14.html#jls-14.4.1
>>>>
>>>> I would be surprised if that could change to allow your second snippet.
>>>> That said, if that functionality is truly required, you can provide it
>>>> yourself.
>>>>
>>>> The design of enums allows you to declare a method on an enum class and
>>>> then override it in a particular constant. Alternatively, you can switch on
>>>> an enum constant to provide constant-specific behaviour "externally".
>>>>
>>>> -Pavel
>>>>
>>>> > On 21 Feb 2024, at 10:08, Red IO <redio.development at gmail.com> wrote:
>>>> >
>>>> > I recently tinkered a bit with java enums. While I was researching
>>>> edge features enums support I came across a stackoverflow post referencing
>>>> the JLS 8.9 saying that the optional body of an enum constant is an
>>>> anonymous class declaration.
>>>> > As for some time now methods declared in an anonymous class assigned
>>>> to a var variable are accessible I tried to do the same for the enum
>>>> constant.
>>>> >
>>>> > var anonymous = new Object() {
>>>> > public void test() {}
>>>> > }
>>>> > anonymous.test(); //works
>>>> >
>>>> >
>>>> > enum Test {
>>>> > A {
>>>> > public void test() {}
>>>> > }
>>>> > }
>>>> > var enumConstant = Test.A;
>>>> > enumConstant.test(); // doesn't work
>>>> >
>>>> > I have a clue to why this doesn't work. It's likely that the type of
>>>> the constant A is the type of the enum and not of the anonymous class.
>>>> >
>>>> > There are some usecases where exclusive methods on enum constants
>>>> might be useful. So it would be nice if this would work.
>>>> >
>>>> > Great regards
>>>> > RedIODev
>>>> >
>>>> >
>>>> >
>>>> >
>>>>
>>>>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://mail.openjdk.org/pipermail/amber-dev/attachments/20240221/9a1c9cf7/attachment.htm>
More information about the amber-dev
mailing list