<!DOCTYPE html><html><head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
  </head>
  <body>
    <font size="4" face="monospace">Here's a snapshot of where my head
      is at with respect to extending the record goodies (including
      pattern matching) to a broader range of classes, deconstructors
      for classes and interfaces, and compatible evolution of records. 
      Hopefully this will unblock quite a few things.<br>
      <br>
      As usual, let's discuss concepts and directions rather than
      syntax.  <br>
      <br>
      <br>
      <br>
      # Data-oriented Programming for Java: Beyond records<br>
      <br>
      Everyone loves records; they allow us to create shallowly
      immutable data holder<br>
      classes -- which we can think of as "nominal tuples" -- derived
      from a concise<br>
      state description, and to destructure records through pattern
      matching.  But<br>
      records have strict constraints, and not all data holder classes
      fit into the<br>
      restrictions of records.  Maybe they have some mutable state, or
      derived or<br>
      cached state that is not part of the state description, or their
      representation<br>
      and their API do not match up exactly, or they need to break up
      their state<br>
      across a hierarchy.  In these classes, even though they may also
      be “data<br>
      holders”, the user experience is like falling off a cliff.  Even a
      small<br>
      deviation from the record ideal means one has to go back to a
      blank slate and<br>
      write explicit constructor declarations, accessor method
      declarations, and<br>
      Object method implementations -- and give up on destructuring
      through pattern<br>
      matching.  <br>
      <br>
      Since the start of the design process for records, we’ve kept in
      mind the goal<br>
      of enabling a broader range of classes to gain access to the
      "record goodies":<br>
      reduced declaration burden, participating in destructuring, and
      soon,<br>
      [reconstruction](<a class="moz-txt-link-freetext" href="https://openjdk.org/jeps/468">https://openjdk.org/jeps/468</a>). During the design
      of records, we<br>
      also explored a number of weaker semantic models that would allow
      for greater<br>
      flexibility. While at the time they all failed to live up to the
      goals _for<br>
      records_, there is a weaker set of semantic constraints we can
      impose that<br>
      allows for more flexibility and still enables the features we
      want, along with<br>
      some degree of syntactic concision that is commensurate with the
      distance from<br>
      the record-ideal, without fall-off-the-cliff behaviors.  <br>
      <br>
      Records, sealed classes, and destructuring with record patterns
      constitute the<br>
      first feature arc of "data-oriented programming" for Java.  After
      considering<br>
      numerous design ideas, we're now ready to move forward with the
      next "data<br>
      oriented programming" feature arc: _carrier classes_ (and
      interfaces.)<br>
      <br>
      ## Beyond record patterns<br>
      <br>
      Record patterns allow a record instance to be destructured into
      its components.<br>
      Record patterns can be used in `instanceof` and `switch`, and when
      a record<br>
      pattern is also exhaustive, will be usable in the upcoming
      [_pattern assignment<br>
statement_](<a class="moz-txt-link-freetext" href="https://mail.openjdk.org/pipermail/amber-spec-experts/2026-January/004306.html">https://mail.openjdk.org/pipermail/amber-spec-experts/2026-January/004306.html</a>)
      feature.  <br>
      <br>
      In exploring the question "how will classes be able to participate
      in the same<br>
      sort of destructuring as records", we had initially focused on a
      new form of<br>
      declaration in a class -- a "deconstructor" -- that operated as a
      constructor in<br>
      reverse. Just as a constructor takes component values and produces
      an aggregate<br>
      instance, a deconstructor would take an aggregate instance and
      recover its<br>
      component values.  <br>
      <br>
      But as this exploration played out, the more interesting question
      turned out to<br>
      be: which classes are suitable for destructuring in the first
      place? And the<br>
      answer to that question led us to a different approach for
      expressing<br>
      deconstruction.  The classes that are suitable for destructuring
      are those that,<br>
      like records, are little more than carriers for a specific tuple
      of data. This<br>
      is not just a thing that a class _has_, like a constructor or
      method, but<br>
      something a class _is_.  And as such, it makes more sense to
      describe<br>
      deconstruction as a top-level property of a class.  This, in turn,
      leads to a<br>
      number of simplifications.  <br>
      <br>
      ## The power of the state description<br>
      <br>
      Records are a semantic feature; they are only incidentally
      concise.  But they<br>
      _are_ concise; when we declare a record<br>
      <br>
          record Point(int x, int y) { ... }<br>
      <br>
      we automatically get a sensible API (canonical constructor,
      deconstruction<br>
      pattern, accessor methods for each component) and implementation
      (fields,<br>
      constructor, accessor methods, Object methods.)  We can explicitly
      specify most<br>
      of these (except the fields) if we like, but most of the time we
      don't have to,<br>
      because the default is exactly what we want.<br>
      <br>
      A record is a shallowly-immutable, final class whose API and
      representation are<br>
      _completely defined_ by its _state description_.  (The slogan for
      records is<br>
      "the state, the whole state, and nothing but the state.")  The
      state description<br>
      is the ordered list of _record components_ declared in the
      record's header.  A<br>
      component is more than a mere field or accessor method; it is an
      API element on<br>
      its own, describing a state element that instances of the class
      have.  <br>
      <br>
      The state description of a record has several desirable
      properties: <br>
      <br>
       - The components in the order specified, are the _canonical_
      description of the<br>
         record's state.<br>
       - The components are the _complete_ description of the record’s
      state.  <br>
       - The components are _nominal_; their names are a committed part
      of the<br>
         record's API.  <br>
      <br>
      Records derive their benefits from making two commitments:<br>
      <br>
       - The _external_ commitment that the data-access API of a record
      (constructor,<br>
         deconstruction pattern, and component accessor methods) is
      defined by the<br>
         state description.  <br>
       - The _internal_ commitments that the _representation_ of the
      record (its<br>
         fields) is also completely defined by the state description.<br>
      <br>
      These semantic properties are what enable us to derive almost
      everything about<br>
      records.  We can derive the API of the canonical constructor
      because the state<br>
      description is canonical.  We can derive the API for the component
      accessor<br>
      methods because the state description is nominal.  And we can
      derive a<br>
      deconstruction pattern from the accessor methods because the state
      description<br>
      is complete (along with sensible implementations for the
      state-related `Object`<br>
      methods.)<br>
      <br>
      The internal commitment that the state description is also the
      representation<br>
      allows us to completely derive the rest of the implementation. 
      Records get a<br>
      (private, final) field for each component, but more importantly,
      there is a<br>
      clear mapping between these fields and their corresponding
      components, which is<br>
      what allows us to derive the canonical constructor and accessor
      method<br>
      implementations.  <br>
      <br>
      Records can additionally declare a _compact constructor_ that
      allows us to elide<br>
      the boilerplate aspects of record constructors -- the argument
      list and field<br>
      assignments -- and just specify the code that is _not_
      mechanically derivable.<br>
      This is more concise, less error-prone, and easier to read:<br>
      <br>
          record Rational(int num, int denom) { <br>
              Rational { <br>
                  if (denom == 0)<br>
                      throw new IllegalArgumentException("denominator
      cannot be zero");<br>
              }<br>
          }<br>
      <br>
      is shorthand for the more explicit<br>
      <br>
          record Rational(int num, int denom) { <br>
              Rational(int num, int denom) { <br>
                  if (denom == 0)<br>
                      throw new IllegalArgumentException("denominator
      cannot be zero");<br>
                  this.num = num;<br>
                  this.denom = denom;<br>
              }<br>
          }<br>
      <br>
      While compact constructors are pleasantly concise, the more
      important benefit is<br>
      that by eliminating the mechanically derivable code, the "more
      interesting" code<br>
      comes to the fore.  <br>
      <br>
      Looking ahead, the state description is a gift that keeps on
      giving.  These<br>
      semantic commitments are enablers for a number of potential future
      language and<br>
      library features for managing object lifecycle, such as: <br>
      <br>
       - [Reconstruction](<a class="moz-txt-link-freetext" href="https://openjdk.org/jeps/468">https://openjdk.org/jeps/468</a>) of record
      instances, allowing<br>
         the appearance of controlled mutation of record state.<br>
       - Automatic marshalling and unmarshalling of record instances.<br>
       - Instantiating or destructuring record instances identifying
      components<br>
         nominally rather than positionally.<br>
      <br>
      ### Reconstruction<br>
      <br>
      JEP 468 proposes a mechanism by which a new record instance can be
      derived from<br>
      an existing one using syntax that is evocative of direct mutation,
      via a `with`<br>
      expression: <br>
      <br>
          record Complex(double re, double im) { }<br>
          Complex c = ...<br>
          Complex cConjugate = c with { im = -im; }; <br>
      <br>
      The block on the right side of `with` can contain any Java
      statements, not just<br>
      assignments.  It is enhanced with mutable variables (_component
      variables_) for<br>
      each component of the record, initialized to the value of that
      component in the<br>
      record instance on the left, the block is executed, and a new
      record instance is<br>
      created whose component values are the ending values of the
      component variables.  <br>
      <br>
      A reconstruction expression implicitly destructures the record
      instance using<br>
      the canonical deconstruction pattern, executes the block in a
      scope enhanced<br>
      with the component variables, and then creates a new record using
      the canonical<br>
      constructor.  Invariant checking is centralized in the canonical
      constructor, so<br>
      if the new state is not valid, the reconstruction will fail.  JEP
      468 has been<br>
      "on hold" for a while, primarily because we were waiting for
      sufficient<br>
      confidence that there was a path to extending it to suitable
      classes before<br>
      committing to it for records.  The ideal path would be for those
      classes to also<br>
      support a notion of canonical constructor and deconstruction
      pattern.  <br>
      <br>
      Careful readers will note a similarity between the transformation
      block of a<br>
      `with` expression and the body of a compact constructor.  In both
      cases, the<br>
      block is "preloaded" with a set of component variables,
      initialized to suitable<br>
      starting values, the block can mutate those variables as desired,
      and upon<br>
      normal completion of the block, those variables are passed to a
      canonical<br>
      constructor to produce the final result.  The main difference is
      where the<br>
      starting values come from; for a compact constructor, it is from
      the constructor<br>
      parameters, and for a reconstruction expression, it is from the
      canonical<br>
      deconstruction pattern of the source record to the left of `with`.<br>
       <br>
      ### Breaking down the cliff<br>
      <br>
      Records make a strong semantic commitment to derive both their API
      and<br>
      representation from the state description, and in return get a lot
      of help from<br>
      the language.  We can now turn our attention to smoothing out "the
      cliff" --<br>
      identifying weaker semantic commitments that classes can make that
      would still<br>
      allow classes to get _some_ help from the language.  And ideally,
      the amount of<br>
      help you give up would be proportional to the degree of deviation
      from the<br>
      record ideal.<br>
      <br>
      With records, we got a lot of mileage out of having a complete,
      canonical,<br>
      nominal state description.  Where the record contract is sometimes
      too<br>
      constraining is the _implementation_ contract that the
      representation aligns<br>
      exactly with the state description, that the class is final, that
      the fields are<br>
      final, and that the class may not extend anything but `Record`.  <br>
      <br>
      Our path here takes one step back and one step forward: keeping
      the external<br>
      commitment to the state description, but dropping the internal
      commitment that<br>
      the state description _is_ the representation -- and then _adding
      back_ a simple<br>
      mechanism for mapping fields representing components back to their
      corresponding<br>
      components, where practical.  (With records, because we derive the<br>
      representation from the state description, this mapping can be
      safely inferred.)  <br>
      <br>
      As a thought experiment, imagine a class that makes the external
      commitment to a<br>
      state description -- that the state description is a complete,
      canonical,<br>
      nominal description of its state -- but is on its own to provide
      its<br>
      representation.  What can we do for such a class?  Quite a bit,
      actually.  For<br>
      all the same reasons we can for records, we can derive the API
      requirement for a<br>
      canonical constructor and component accessor methods.  From there,
      we can derive<br>
      both the requirement for a canonical deconstruction pattern, and
      also the<br>
      implementation of the deconstruction pattern (as it is implemented
      in terms of<br>
      the accessor methods). And since the state description is
      complete, we can<br>
      further derive sensible default implementations of the Object
      methods `equals`,<br>
      `hashCode`, and `toString` in terms of the accessor methods as
      well. And given<br>
      that there is a canonical constructor and deconstruction pattern,
      it can also<br>
      participate in reconstruction.  The author would just have to
      provide the<br>
      fields, accessor methods, and canonical constructor.  This is good
      progress, but<br>
      we'd like to do better.<br>
      <br>
      What enables us to derive the rest of the implementation for
      records (fields,<br>
      constructor, accessor methods, and Object methods) is the
      knowledge of how the<br>
      representation maps to the state description.  Records commit to
      their state<br>
      description _being_ the representation, so is is a short leap from
      there to a<br>
      complete implementation.  <br>
      <br>
      To make this more concrete, let's look at a typical "almost
      record" class, a<br>
      carrier for the state description `(int x, int y,
      Optional<String> s)` but which<br>
      has made the representation choice to internally store `s` as a
      nullable<br>
      `String`.  <br>
      <br>
      ```<br>
      class AlmostRecord { <br>
          private final int x;<br>
          private final int y;<br>
          private final String s;                                 // *<br>
      <br>
          public AlmostRecord(int x, int y, Optional<String> s) { <br>
              this.x = x;<br>
              this.y = y;<br>
              this.s = s.orElse(null);                            // *<br>
          }<br>
      <br>
          public int x() { return x; }<br>
          public int y() { return y; }<br>
          public Optional<String> s() { <br>
              return Optional.ofNullable(s);                      // *<br>
          }<br>
      <br>
          public boolean equals(Object other) { ... }     // derived
      from x(), y(), s()<br>
          public int hashCode() { ... }                   //    "<br>
          public String toString() { ... }                //    "<br>
      }<br>
      ```<br>
      <br>
      The main differences between this class and the expansion of its
      record analogue<br>
      are the lines marked with a `*`; these are the ones that deal with
      the disparity<br>
      between the state description and the actual representation.  It
      would be nice<br>
      if the author of this class _only_ had to write the code that was
      different from<br>
      what we could derive for a record; not only would this be
      pleasantly concise,<br>
      but it would mean that all the code that _is_ there exists to
      capture the<br>
      differences between its representation and its API.  <br>
      <br>
      ## Carrier classes<br>
      <br>
      A _carrier class_ is a normal class declared with a state
      description.  As with<br>
      a record, the state description is a complete, canonical, nominal
      description of<br>
      the class's state.  In return, the language derives the same API
      constraints as<br>
      it does for records: canonical constructor, canonical
      deconstruction pattern,<br>
      and component accessor methods.<br>
      <br>
         class Point(int x, int y) {                // class, not
      record!<br>
             // explicitly declared representation<br>
      <br>
             ...<br>
      <br>
             // must have a constructor taking (int x, int y)<br>
             // must have accessors for x and y<br>
             // supports a deconstruction pattern yielding (int x, int
      y)<br>
         }<br>
      <br>
      Unlike a record, the language makes no assumptions about the
      object's<br>
      representation; the class author has to declare that just as with
      any other<br>
      class.  <br>
      <br>
      Saying the state description is "complete" means that it carries
      all the<br>
      “important” state of the class -- if we were to extract this state
      and recreate<br>
      the object, that should yield an “equivalent” instance.  As with
      records, this<br>
      can be captured by tying together the behavior of construction,
      accessors, and<br>
      equality:<br>
      <br>
      ```<br>
      Point p = ...<br>
      Point q = new Point(p.x(), p.y());<br>
      assert p.equals(q);<br>
      ```<br>
      <br>
      We can also derive _some_ implementation from the information we
      have so far; we<br>
      can derive sensible implementations of the `Object` methods
      (implemented in terms<br>
      of component accessor methods) and we can derive the canonical
      deconstruction<br>
      pattern (again in terms of the component accessor methods).  And
      from there, we<br>
      can derive support for reconstruction (`with` expressions.) 
      Unfortunately, we<br>
      cannot (yet) derive the bulk of the state-related implementation:
      the canonical<br>
      constructor and component accessor methods.  <br>
      <br>
      ### Component fields and accessor methods<br>
      <br>
      One of the most tedious aspects of data-holder classes is the
      accessor methods;<br>
      there are often many of them, and they are almost always pure
      boilerplate.  Even<br>
      though IDEs can reduce the writing burden by generating these for
      us, readers<br>
      still have to slog through a lot of low-information code -- just
      to learn that<br>
      they didn't actually need to slog through that code after all.  We
      can derive<br>
      the implementation of accessor methods for records because records
      make the<br>
      internal commitment that the components are all backed with
      individual fields<br>
      whose name and type align with the state description.  <br>
      <br>
      For a carrier class, we don't know whether _any_ of the components
      are directly<br>
      backed by a single field that aligns to the name or type of the
      component.  But<br>
      it is a pretty good bet that many carrier class components will do
      exactly this<br>
      for at least _some_ of their fields.  If we can tell the language
      that this<br>
      correspondence is not merely accidental, the language can do more
      for us.<br>
      <br>
      We do so by allowing suitable fields of a carrier class to be
      declared as<br>
      `component` fields.  (As usual at this stage, syntax is
      provisional, but not <br>
      currently a topic for discussion.)  A component field must have
      the same name<br>
      and type as a component of the current class (though it need not
      be `private` or<br>
      `final`, as record fields are.)  This signals that this field _is_
      the<br>
      representation for the corresponding component, and hence we can
      derive the<br>
      accessor method for this component as well.  <br>
      <br>
      ```<br>
      class Point(int x, int y) { <br>
          private /* mutable */ component int x;<br>
          private /* mutable */ component int y;<br>
      <br>
          // must have a canonical constructor, but (so far) must be
      explicit<br>
          public Point(int x, int y) { <br>
              this.x = x;<br>
              this.y = y;<br>
          }<br>
      <br>
          // derived implementations of accessors for x and y<br>
          // derived implementations of equals, hashCode, toString<br>
      }<br>
      ```<br>
      <br>
      This is getting better; the class author had to bring the
      representation and the<br>
      mapping from representation to components (in the form of the
      `component`<br>
      modifier), and the canonical constructor.  <br>
      <br>
      ### Compact constructors<br>
      <br>
      Just as we are able to derive the accessor method implementation
      if we are<br>
      given an explicit correspondence between a field and a component,
      we can do the<br>
      same for constructors.  For this, we build on the notion of
      _compact<br>
      constructors_ that was introduced for records.  <br>
      <br>
      As with a record, a compact constructor in a carrier class is a
      shorthand for a<br>
      canonical constructor, which has the same shape as the state
      description, but<br>
      which is freed of the responsibility of actually committing the
      ending value of<br>
      the component parameters to the fields.  The main difference is
      that for a<br>
      record, _all_ of the components are backed by a component field,
      whereas for a<br>
      carrier class, only some of them might be.  But we can generalize
      compact<br>
      constructors by freeing the author of the responsibility to
      initialize the<br>
      _component_ fields, while leaving them responsible for
      initializing the rest of<br>
      the fields.  In the limiting case where all components are backed
      by component<br>
      fields, and there is no other logic desired in the constructor,
      the compact<br>
      constructor may be elided.  <br>
      <br>
      For our mutable `Point` class, this means we can elide nearly
      everything, except<br>
      the field declarations themselves: <br>
      <br>
      ```<br>
      class Point(int x, int y) { <br>
          private /* mutable */ component int x;<br>
          private /* mutable */ component int y;<br>
      <br>
          // derived compact constructor<br>
          // derived accessors for x, y<br>
          // derived implementations of equals, hashCode, toString<br>
      }<br>
      ```<br>
      <br>
      We can think of this class as having an implicit empty compact
      constructor,<br>
      which in turn means that the component fields `x` and `y` are
      initialized from<br>
      their corresponding constructor parameters.  There are also
      implicitly derived<br>
      accessor methods for each component, and implementations of
      `Object` methods<br>
      based on the state description.  <br>
      <br>
      This is great for a class where all the components are backed by
      fields, but<br>
      what about our `AlmostRecord` class?  The story here is good as
      well; we can<br>
      derive the accessor methods for the components backed by component
      fields, and<br>
      we can elide the initialization of the component fields from the
      compact<br>
      constructor, meaning that we _only_ have to specify the code for
      the parts that<br>
      deviate from the "record ideal": <br>
      <br>
      ```<br>
      class AlmostRecord(int x, <br>
                         int y, <br>
                         Optional<String> s) { <br>
      <br>
          private final component int x;<br>
          private final component int y;<br>
          private final String s;<br>
      <br>
          public AlmostRecord { <br>
              this.s = s.orElse(null); <br>
              // x and y fields implicitly initialized<br>
          }<br>
      <br>
          public Optional<String> s() { <br>
              return Optional.ofNullable(s);  <br>
          }<br>
      <br>
          // derived implementation of x and y accessors<br>
          // derived implementation of equals, hashCode, toString<br>
      }<br>
      ```<br>
      <br>
      Because so many real-world almost-records differ from their record
      ideal in<br>
      minor ways, we expect to get a significant concision benefit for
      most carrier<br>
      classes, as we did for `AlmostRecord`.  As with records, if we
      want to<br>
      explicitly implement the constructor, accessor methods, or
      `Object` methods, we<br>
      are still free to do so. <br>
      <br>
      ### Derived state<br>
      <br>
      One of the most frequent complaints about records is the inability
      to derive<br>
      state from the components and cache it for fast retrieval.  With
      carrier<br>
      classes, this is simple: declare a non-component field for the
      derived quantity,<br>
      initialize it in the constructor, and provide an accessor: <br>
      <br>
      ```<br>
      class Point(int x, int y) { <br>
          private final component int x;<br>
          private final component int y;<br>
          private final double norm;<br>
      <br>
          Point { <br>
              norm = Math.hypot(x, y);<br>
          }<br>
      <br>
          public double norm() { return norm; }<br>
      <br>
          // derived implementation of x and y accessors<br>
          // derived implementation of equals, hashCode, toString<br>
      }<br>
      ```<br>
      <br>
      ### Deconstruction and reconstruction<br>
      <br>
      Like records, carrier classes automatically acquire deconstruction
      patterns that<br>
      match the canonical constructor, so we can destructure our `Point`
      class as if<br>
      it were a record: <br>
      <br>
          case Point(var x, var y): <br>
      <br>
      Because reconstruction (`with`) derives from a canonical
      constructor and<br>
      corresponding deconstruction pattern, when we support
      reconstruction of records,<br>
      we will also be able to do so for carrier classes:<br>
      <br>
          point = point with { x = 3; }<br>
      <br>
      ## Carrier interfaces<br>
      <br>
      A state description makes sense on interfaces as well.  It makes
      the statement<br>
      that the state description is a complete, canonical, nominal
      description of the<br>
      interface's state (subclasses are allowed to add additional
      state), and<br>
      accordingly, implementations must provide accessor methods for the
      components.<br>
      This enables such interfaces to participate in pattern matching:<br>
      <br>
      ```<br>
      interface Pair<T,U>(T first, U second) {<br>
          // implicit abstract accessors for first() and second()<br>
      }<br>
      <br>
      ...<br>
      <br>
      if (o instanceof Pair(var a, var b)) { ... }<br>
      ```<br>
      <br>
      Along with the upcoming feature for pattern assignment in
      foreach-loop headers,<br>
      if `Map.Entry` became a carrier interface (which it will), we
      would be able to<br>
      iterate a `Map` like:<br>
      <br>
          for (Map.Entry(var key, var val) : map.entrySet()) { ... }<br>
      <br>
      It is a common pattern in libraries to export an interface that is
      sealed to a<br>
      single private implementation.  In this pattern, the interface and<br>
      implementation can share a common state description: <br>
      <br>
      ```<br>
      public sealed interface Pair<T,U>(T first, U second) { }<br>
      <br>
      private record PairImpl<T, U>(T first, U second) implements
      Pair<T, U> { }<br>
      ```<br>
      <br>
      Compared to the old way of doing this, we get enhanced semantics,
      better type<br>
      checking, and more concision.  <br>
      <br>
      ### Extension<br>
      <br>
      The main obligation of a carrier class author is to ensure that
      the fundamental<br>
      claim -- that the state description is a complete, canonical,
      nominal<br>
      description of the object's state -- is actually true.  This does
      not rule out<br>
      having the representation of a carrier class spread out over a
      hierarchy, so<br>
      unlike records, carrier classes are not required to be final or
      concrete, nor<br>
      are they restricted in their extension.<br>
      <br>
      There are several cases that arise when carrier classes can
      participate in<br>
      extension:<br>
      <br>
       - A carrier class extends a non-carrier class;<br>
       - A non-carrier class extends a carrier class;<br>
       - A carrier class extends another carrier class, where all of the
      superclass<br>
         components are subsumed by the subclass state description; <br>
       - A carrier class extends another carrier class, but there are
      one or more<br>
         superclass components that are not subsumed by the subclass
      state<br>
         description.<br>
      <br>
      Extending a non-carrier class with a carrier class will usually be
      motiviated by<br>
      the desire to "wrap" a state description around an existing
      hierarchy which we<br>
      cannot or do not want to modify directly, but we wish to gain the
      benefits of<br>
      deconstruction and reconstruction.  Such an implementation would
      have to ensure<br>
      that the class actually conforms to the state description, and
      that the<br>
      canonical constructor and component accessors are implemented.  <br>
      <br>
      When one carrier class extends another, the more straightforward
      case is that it<br>
      simply adds new components to the state description of the
      superclass.  For<br>
      example, given our `Point` class:<br>
      <br>
      ```<br>
      class Point(int x, int y) { <br>
          component int x; <br>
          component int y;<br>
      <br>
          // everything else for free!<br>
      }<br>
      ```<br>
      <br>
      we can use this as the base class for a 3d point class: <br>
      <br>
      ```<br>
      class Point3d(int x, int y, int z) extends Point { <br>
          component int z;<br>
      <br>
          Point3d {<br>
              super(x, y);<br>
          }<br>
      }<br>
      ```<br>
      <br>
      In this case -- because the superclass components are all part of
      the subclass<br>
      state description -- we can actually omit the constructor as well,
      because we<br>
      can derive the association between subclass components and
      superclass<br>
      components, and thereby derive the needed super-constructor
      invocation.  So we<br>
      could actually write:<br>
      <br>
      ```<br>
      class Point3d(int x, int y, int z) extends Point { <br>
          component int z;<br>
      <br>
          // everything else for free!<br>
      }<br>
      ```<br>
      <br>
      One might think that we would need some marking on the `x` and `y`
      components of<br>
      `Point3d` to indicate that they map to the corresponding
      components of `Point`,<br>
      as we did for associating component fields with their
      corresponding components.<br>
      But in this case, we need no such marking, because there is no way
      that an `int<br>
      x` component of `Point` and an `int x` component of its subclass
      could possibly<br>
      refer to different things -- since they both are tied to the same
      `int x()`<br>
      accessor methods.  So we can safely infer which subclass
      components are managed<br>
      by superclasses, just by matching up their names and types.<br>
      <br>
      In the other carrier-to-carrier extension case, where one or more
      superclass<br>
      components are _not_ subsumed by the subclass state description,
      it is necessary<br>
      to provide an explicit `super` constructor call in the subclass
      constructor.  <br>
      <br>
      A carrier class may be also declared abstract; the main effect of
      this is that<br>
      we will not derive `Object` method implementations, instead
      leaving that for the<br>
      subclass to do.<br>
      <br>
      ### Abstract records<br>
      <br>
      This framework also gives us an opportunity to relax one of the
      restrictions on<br>
      records: that records can't extend anything other than
      `java.lang.Record`.  We<br>
      can also allow records to be declared `abstract`, and for records
      to extend<br>
      abstract records.  <br>
      <br>
      Just as with carrier classes that extend other carrier classes,
      there are two<br>
      cases: when the component list of the superclass is entirely
      contained within<br>
      that of the subclass, and when one or more superclass components
      are derived<br>
      from subclass components (or are constant), but are not components
      of the<br>
      subclass itself.  And just as with carrier classes, the main
      difference is<br>
      whether an explicit `super` call is required in the subclass
      constructor.  <br>
      <br>
      When a record extends an abstract record, any components of the
      subclass that<br>
      are also components of the superclass do not implicitly get
      component fields in<br>
      the subclass (because they are already in the superclass), and
      they inherit the<br>
      accessor methods from the superclass.  <br>
      <br>
      ### Records are carriers too<br>
      <br>
      With this framework in place, records can now be seen to be "just"
      carrier<br>
      classes that are implicitly final, extend `java.lang.Record`, that
      implicitly<br>
      have private final component fields for each component, and can
      have no other<br>
      fields.  <br>
      <br>
      ## Migration compatibility <br>
      <br>
      There will surely be some existing classes that would like to
      become carrier<br>
      classes.  This is a compatible migration as long as none of the
      mandated members<br>
      conflict with existing members of the class, and the class adheres
      to the<br>
      requirement that the state description is a complete, canonical,
      and nominal<br>
      description of the object state.  <br>
      <br>
      ### Compatible evolution of records and carrier classes<br>
      <br>
      To date, libraries have been reluctant to use records in public
      APIs because<br>
      of the difficulty of evolving them compatibly.  For a record: <br>
      <br>
      ```<br>
      record R(A a, B b) { }<br>
      ```<br>
      <br>
      that wants to evolve by adding new components:<br>
      <br>
      ```<br>
      record R(A a, B b, C c, D d) { }<br>
      ```<br>
      <br>
      we have several compatibility challenges to manage.  As long as we
      are only<br>
      adding and not removing/renaming, accessor method invocations will
      continue to<br>
      work. And existing constructor invocations can be allowed to
      continue work by<br>
      explicitly adding back a constructor that has the old shape: <br>
      <br>
      ```<br>
      record R(A a, B b, C c, D d) { <br>
      <br>
          // Explicit constructor for old shape required<br>
          public R(A a, B b) { <br>
              this(a, b, DEFAULT_C, DEFAULT_D);<br>
          }<br>
      <br>
      }<br>
      ```<br>
      <br>
      But, what can we do about existing uses of record _patterns_? 
      While the<br>
      translation of record patterns would make adding components
      binary-compatible,<br>
      it would not be source-compatible, and there is no way to
      explicitly add a<br>
      deconstruction pattern for the old shape as we did with the
      constructor.  <br>
      <br>
      We can take advantage of the simplification offered by there being
      _only_ the<br>
      canonical deconstruction pattern, and allow uses of deconstruction
      patterns to<br>
      supply nested patterns for any _prefix_ of the component list.  So
      for the<br>
      evolved record R: <br>
      <br>
          case R(P1, P2)<br>
      <br>
      would be interpreted as:<br>
      <br>
          case R(P1, P2, _, _)<br>
      <br>
      where `_` is the match-all pattern.  This means that one can
      compatibly evolve a<br>
      record by only adding new components at the end, and adding a
      suitable<br>
      constructor for compatibility with existing constructor
      invocations.<br>
      <br>
    </font>
  </body>
</html>