The interfaces IdentityObject and ValueObject must die !
Remi Forax
forax at univ-mlv.fr
Tue Jan 25 21:39:25 UTC 2022
I think we should revisit the idea of having the interfaces IdentityObject/ValueObject.
They serve two purposes
1/ documentation: explain the difference between an identity class and a value class
2/ type restriction: can be used as type or bound of type parameter for algorithms that only works with identity class
Sadly, our design as evolved but not those interfaces, they do not work well as type restriction, because
the type is lost once an interface/j.l.Object is used and the cost of their introduction is higher than previously though.
1/ documentation
- Those interface split the possible types in two groups
but the spec split the types in 3, B1/B2/B3, thus they are not aligned anymore with the new design.
- they will be noise in the future, for Valhalla, the separation between identity object and value object
may be important but from a POV of someone learning/discovering the language it's a corner case
(like primitives are). This is even more true with the introduction of B2, you can use B2 for a long time without
knowing what a value type is. So having such interfaces front and center is too much.
2/ as type
- Being a value class or a primitive class is a runtime behavior not a compile time behavior,
so representing them with special types (a type is a compile time construct) will always be an approximation.
As a consequence, you can have an identity class (resp value class) typed with a type which is not a subtype
of IdentityObject (resp ValueObject).
This discrepancy is hard to grasp for beginners (in fact not only for beginners) and make IdentityObject/ValueObject
useless because if a method takes an IdentityObject as parameter but the type is an interface, users will have
to cast it into an IdentityObject which defeat the purpose of having such interface.
(This is the reason why ObjectOutputStream.writeObject() takes an Object as parameter and not Serializable)
And the cost of introduction is high
- they are not source backward compatible
class A {}
class B {}
var list = List.of(new A(), new B());
List<Object> list2 = list;
- they are not binary backward compatible
new Object().getClass() != Object.class
- at least IdentityObject needs to be injected at runtime, which by side effect requires patching several
VM components: reflection/j.l.invoke, JVMTI, etc making the VM spec more complex that it should be.
You may not agree with some of my points, nevertheless, the current design is not aligned with the B1/B2/B3 world, have a high cost and with little benefit so i think it's time to remove those interfaces from the design.
regards,
Rémi
More information about the valhalla-spec-observers
mailing list