<div dir="auto">I think if we are talking about the initial question again the elephant in the room is the lack of a way to express subtypes in supertypes (F-bounds) without using "hacks" like the recursive generic. That this (mis)use of generics is confusing is demonstrated in this thread and in many others.<div dir="auto">A good solution would be to introduce a "This" type that always refers to the current class type even when inheriting. I'm by far not the first person to suggest that.</div><div dir="auto">But the bigger problem is that this ship has sailed for the Enum class. Even if the This type was introduced now and used in Enum removing the generic parameter would be a braking change to the Enum class braking every code that relies on the parameter to be present.</div><div dir="auto">The possibility to add This regardless of the Enum class should still be considered thought. </div><div dir="auto"><br></div><div dir="auto">Great regards </div><div dir="auto">RedIODev </div></div><br><div class="gmail_quote"><div dir="ltr" class="gmail_attr">On Wed, Mar 29, 2023, 04:45 Brian Goetz <<a href="mailto:brian.goetz@oracle.com">brian.goetz@oracle.com</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><br>
> This somewhat clears it up. Are you basically saying that the only <br>
> reason why the supertype can know about the subtype is because the <br>
> relationship is recursive, and thus, the recursion allows the <br>
> supertype to "know" about the subtype because the subtype is just a <br>
> roundabout way of referencing itself - something the supertype DOES <br>
> have access to?<br>
<br>
F-bounds are weird-looking at first:<br>
<br>
     abstract class Enum<T extends Enum<T>> { ... }<br>
<br>
in part because it's not always obvious what "T" means at first. We're <br>
used to seeing type variables that represent element types (List<T>), or <br>
result types (Supplier<T>), but this T really means "subclass".  If it <br>
were written<br>
<br>
     abstract class Enum<Subclass extends Enum<Subclass>> { Subclass[] <br>
values(); }<br>
<br>
it would already be clearer.  You might first try writing it as<br>
<br>
     abstract class Enum<Subclass> { ... }<br>
<br>
but this permits extension in unexpected ways:<br>
<br>
     class FooEnum extends Enum<String> { ... }<br>
<br>
You could try refining it as<br>
<br>
     abstract class Enum<Subclass extends Enum> { ... }<br>
<br>
but this still permits<br>
<br>
     class FooEnum extends Enum<BarEnum> { ... }<br>
<br>
What we're trying to express is that the type argument of Enum *is* the <br>
class being declared.  Which is where the f-bound comes in:<br>
<br>
     abstract class Enum<Subclass extends Enum<Subclass>> { Subclass[] <br>
values(); }<br>
<br>
which can only be satisfied by a declaration of the form<br>
<br>
     class X extends Enum<X> { ... }<br>
<br>
The first few times you look at it, it seems weird and magic, and then <br>
at some point it seems obvious :)<br>
</blockquote></div>