On Jan 26, 2022, at 2:18 AM, fo...@univ-mlv.fr<mailto:fo...@univ-mlv.fr> wrote:

In other words: I don't see a use case for distinguishing between primitive and
value classes with different interfaces.

Primitive classes does not allow nulls and are tearable, following your logic, 
there should be a subclass of ValueObject named PrimitiveObject that reflects 
that semantics.

But this isn't a property of the *class*, it's a property of the *type*, as 
used at a particular use site. If you want to know whether an array is 
flattened, the class of the component can't tell you.

This is especially useful when you have an array of PrimitiveObject, you know 
that a storing null in an array of PrimitiveObject will always generate a NPE 
at runtime and that you may have to use either the volatile semantics or a lock 
when you read/write values from/to the array of PrimitiveObject.

For examples,
 public void m(PrimitiveObject[] array, int index) {
   array[index] = null;  // can be a compile time error
 }

If we said

class Point implements PrimitiveObject

then it would be the case that

Point.ref[] <: PrimitiveObject[]

and so PrimitiveObject[] wouldn't mean what you want it to mean.

We could make a special rule that says primitive types are subtypes of a 
special interface, even though their class does not implement that interface. 
But that doesn't really work, either—primitive types are monomorphic. If you've 
got a variable with an interface type, you've got a reference.

We could also make a special rule that says arrays of primitive types implement 
an interface PrimitiveArray. More generally, we've considered enhancements to 
arrays where there are different implementations provided by different classes. 
That seems plausible, but it's orthogonal to the IdentityObject/ValueObject 
feature.

Meanwhile, I'd suggest writing the method like this, using universal generics:

<T>  public void m(T[] array, int index) {
   array[index] = null;  // null warning
 }

An impossible type, it's a type that can be declared but no class will ever 
match.

Examples of impossible types, at declaration site
 interface I extends ValueObject {}
 interface J extends IdentityObject {}
 <T extends I & J> void foo() { }

It would definitely be illegal to declare a class that extends I and J. Our 
rules about well-formedness for bounds have always been sketchy, but 
potentially that would be a malformed type variable.

Abandoning the property entirely would be a bigger deal.

If we do not use interfaces, the runtime class of java.lang.Object can be 
Object, being an identity class or not is a just a bit in the reified class, 
not a compile time property, there is contamination by inheritance.

Object can't be an identity class, at compile time or run time, because some 
subclasses of Object are value classes.

What you'd need is a property of individual *objects*, not represented at all 
with the class. Theoretically possible, but like I said, a pretty big 
disruption to our current model.

For me, it's like opening the door of your house to an elephant because it has 
a nice hat and saying you will fix that with scotch-tape each time it touches 
something.

Ha. This sounds like maybe there's a French idiom involved, but anyway we 
should try to get John to add this to his repertoire of analogies.

Reply via email to