Recommended usage: declare implementations as readonly class (PHP 8.2+) to enforce the
* immutability contract at the language level. Mutable properties violate Value Object semantics even when
* equals and hashCode still function. Properties must be declared
* public; non-public properties are invisible to the equality and hashing engine.
Equality is structural and recursive. Two Value Objects are equal when they share the same concrete
* class and every paired property is equal: scalars compare by value, nested
* {@see ValueObject} properties delegate to their own equals, arrays compare
* by keys in the same order with values compared recursively, and enums compare by case identity.
Properties holding objects that are not Value Objects (for example, DateTimeImmutable)
* are compared by instance identity. Wrap such values in a dedicated Value Object when value semantics
* are desired.
The contract pairs with {@see ValueObject::equals}: when $a->equals($b)
* holds, $a->hashCode() === $b->hashCode() also holds. Repeated calls on the same instance
* return the same hash within a single process. Stability across library versions is not guaranteed.