On 26 Jan 2022, at 7:42, Dan Smith wrote:
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.