Is there a way to make that work in Java, so that
identity-free classes can inherit from each other?
Probably, in some limited way. The simplest move
is the one Brian and I are liking here, where a
completely non-concrete class (one with no fields
and no commitment to object identity) can be
refined by a subclass. But it should be marked
abstract, so as not to have cases where you have
a variable of the super-type and you don’t know
whether it has the layout of the super (because
it was concrete, oops) or a subtype.
This is the second turn of the crank (the first was "you can extend
Object only"), but as this conversation hinted, there may be a further
turn where abstract identity-agnostic classes can contribute to the
layout and initialization of a concrete final by-value class without
pulling it into the world of new-dup-init. The following is an
exploration, not a proposal, but might help find the next turn of the
crank. The exposition is translational-centric but that's not essential.
An abstract class can contribute fields, initialization of those fields,
and behavior. We can transform:
abstract class C extends ValueObject { // no identity children, please
T t;
C(T t) { ... t = e ... }
}
into
interface C {
abstract <V extends C> protected V withT(V v, T t);
abstract protected T t();
static<V extends C> protected V init(V v, T t) {
... v = withT(v, e) ...
return v;
}
}
and a subclass
b2-class V extends C {
U u;
V(T t, U u) { super(t); u = e; }
}
into
b2-class V implements C {
T t; // pull down fields from super
U u;
V(T t, U u) {
V this = initialvalue;
this = C.init(this, t);
this = this withfield[u] u;
}
}
The point of this exercise is to observe that the two components of C
that are doing double-duty as both API points for clients of C and
extension points for subclasses of C -- the constructor and the layout
-- can be given new implementations for the by-value world, that is
consistent with the inheritance semantics the user expects.
Again, not making a proposal here, as much as probing at the bounds of a
new object model.
(I think this is similar to what you sketched in your next mail.)
The division separating non-concrete types from
identity-object types in the Old Bucket may be
seen in this diagram, which I cobbled up this
weekend:
http://cr.openjdk.java.net/~jrose/values/type-kinds-venn.pdf
This comes from my attempts to make a more or
less comprehensive Venn-style diagram of the stuff
we are talking about. I think it helps me better
visualize what we are trying to do; maybe it will
help others in some way.
I view this as my due diligence mapping the side of the
elephant I can make contact with. Therefore I’m happy
to take corrections on it.
I’m also noodling on a whimsical Field Guide, which asks
you binary questions about a random Java type, and guides
you towards classifying it. That helped me crystallize
the diagram, and may be useful in its own right,
or perhaps distilled into a flowchart. Stay tuned.
— John
On Nov 18, 2021, at 2:34 PM, Brian Goetz <brian.go...@oracle.com> wrote:
I think it is reasonable to consider allowing bucket two classes to
be abstract. They could be extended by other classes which would
either be abstract or final. The intermediate types are polymorphic
but the terminal type is monomorphic.
A similar argument works for records.
Sent from my iPad
On Nov 18, 2021, at 5:27 PM, Kevin Bourrillion <kev...@google.com>
wrote:
On Wed, Nov 17, 2021 at 7:05 PM Dan Heidinga <heidi...@redhat.com>
wrote:
Let me turn the question around: What do we gain by allowing
subclassing of B2 classes?
I'm not claiming it's much. I'm just coming into this from a
different direction.
In my experience most immutable (or stateless) classes have no real
interest in exposing identity, but just get defaulted into it. Any
dependency on the distinction between one instance and another that
equals() it would be a probable bug.
When B2 exists I see myself advocating that a developer's first
instinct should be to make new classes in B2 except when they
/need/ something from B1 like mutability (and perhaps
subclassability belongs in this list too!). As far as I can tell,
this makes sense whether there are even /any /performance benefits
at all, and the performance benefits just make it a lot more
/motivating/ to do what is already probably technically best anyway.
Now, if subclassability legitimately belongs in that list of
B1-forcing-factors, that'll be fine, I just hadn't fully thought it
through and was implicitly treating it like an open question, which
probably made my initial question in this subthread confusing.
--
Kevin Bourrillion | Java Librarian | Google, Inc. |kev...@google.com