On Jan 26, 2022, at 4:55 PM, John Rose 
<john.r.r...@oracle.com<mailto:john.r.r...@oracle.com>> wrote:

Independently of that, for the specific case of Object, having a query function 
Class.instanceKind, which returns “NONE” for abstracts else “VALUE” or 
“IDENTITY”, would encode the same information we are looking at with those 
marker interfaces.

Right, so you're envisioning a move in which, rather than 'obj instanceof 
ValueObject', the dynamic test is 'obj.getClass().instanceKind() == VALUE'.

For dynamic testing (my #3), sure, these are equivalent.


But the contract for a method is more flexible than the contract of a marker 
interface.

In particular, instanceKind is not required to report the same thing for T and 
U when T<:U but marker interfaces are forced to be consistent across T<:U. I 
think this is an advantage, precisely because it has more flexible structure, 
for the method rather than the marker interface.

I would expect that 'cls.instanceKind() == IDENTITY' has the exact same 
semantics as 'IdentityObject.class.isAssignableFrom(cls)': if a class claims to 
be an identity class, then all its instances (direct and via subclassing) are 
identity objects. I'm not seeing a sensible alternative.

How does this behave in the odd world in which direct instances of Object are 
identity objects?

'Object.class.instanceKind()' must return NONE, just as Object.class must not 
implement either IdentityObject or ValueObject.

Given one of these oddball objects, 'obj.getClass().instanceKind()' will, 
naturally, return NONE. Which is surprising, breaking the expectation that 
there are only two possible results of this expression. Just as these objects 
would break the expectation that every object is either 'instanceof 
IdentityObject' or 'instanceof ValueObject'.

I keep saying this: how we handle the 'new Object()' problem doesn't seem to me 
to have any impact on how we encode "I'm an identity class". It's not a 
discussion that belongs in this email thread.


If the marker interfaces also have little use as textual types (e.g., for 
bounds and method parameters) then I agree with Remi. Ditch ‘em.

I outlined many ways in which we're making use of these interfaces. Static 
types is just one. Getting rid of them isn't as easy as "ditch 'em", it would 
involve redesigning for all of those use cases (plus any I forgot), and coming 
up with something that is compellingly better. (This is an invitation, for 
anyone interested in proposing something specific...)

Reply via email to