identityless objects and the type hierarchy
Brian Goetz
brian.goetz at oracle.com
Wed Nov 3 19:42:55 UTC 2021
On 11/3/2021 3:00 PM, Kevin Bourrillion wrote:
> Okay, let's stick a pin in proper-value-types (i.e. try to leave them
> out of this discussion) for a moment...
>
> One question is whether the existing design for the bifurcated type
> hierarchy will carry right over to this split instead. (My
> understanding of that design is: every (non-Object) concrete class
> will implement exactly one of two disjoint interfaces, explicitly or not.)
>
> My first thoughts were that the situation is different here: exposed
> identity seems to be strictly (maybe?) contractually stronger than no
> exposed identity. So here, a class being "noncommittal" /ought to/
> look the same as it being identityless. In theory, it should be
> harmless for an identity class to extend an identityless class (while
> the opposite direction is a problem).
>
> So, first, is that even right?
We went back and forth on this a few times. A useful lens is to ask:
how might we depend on reflecting identity-{ful,less}ness in the
hierarchy? These include:
if (x instanceof IdentityObject) { ... }
void m(IdentityObject o) { ... }
<T extends IdentityObject> m(T t) { ... }
It is worth noting that the first is invertible (we can negate the
condition) but the latter two are not. Which is another way to say
that, if anyone, anywhere, might want to write code that *requires* no
identity, then we should consider giving them a way to do it.
(Ideally, if you're planning on (say) synchronizing on a parameter, you
should engage the type system to ensure that an identityful object is
passed; this is a good use of the type system.)
> Next, even if so, the Backward Default Problem strikes again. To make
> a class identityless you would seem to need all your /supertypes/ to
> be, first! That's hard to pull off. And `Object` itself would seem to
> want to be marked identityless, which is obviously weird/problematic.
The superclass chain is tricky, but we've spent a lot of time shaking
this box. Some types are _identity-agnostic_. These include interfaces
that do not extend PrimitiveObject, abstract classes that meet some set
of conditions, and Object. The supertypes of a primitive class (and of
an identity-agnostic class) must be identity-agnostic.
This is powerful. For example, an interface could extend
IdentityObject, which would effectively prohibit primitive classes from
implementing it. This is a way to signal "my (concrete) subtypes need
identity."
More information about the valhalla-spec-observers
mailing list