On Jan 26, 2022, at 2:18 AM, [email protected]<mailto:[email protected]> 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.