<!DOCTYPE html><html><head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
  </head>
  <body>
    <blockquote type="cite" cite="mid:1085557496.17567763.1768646213005.JavaMail.zimbra@univ-eiffel.fr">
      <div style="font-family: arial, helvetica, sans-serif; font-size: 12pt; color: #000000">
        <div>In my opinion, providing a way to automatically generate
          equals/hashCode and toString() for a mutable class is just a
          giant footgun.</div>
      </div>
    </blockquote>
    <br>
    This is actually one of the fundamental design questions here, so
    I'm glad you brought it up.  (But I will point out that the word
    "footgun" is not a magic wand; the claim that "there is risk" does
    not, in itself, mean the approach is flawed.  Very often there is
    risk in both directions, and we have to choose the lesser.)<br>
    <br>
    Shall I assume that, modulo the handling of carriers with mutable
    fields, you agree with the rest?  I would be happy to have only one
    topic to discuss.  <br>
    <br>
    <blockquote type="cite" cite="mid:1085557496.17567763.1768646213005.JavaMail.zimbra@univ-eiffel.fr">
      <div style="font-family: arial, helvetica, sans-serif; font-size: 12pt; color: #000000">
        <div>With a mutable class with equals/hashCode/toString
          generated, it's too easy to store an object in a collection,
          mutate it, and then never been able to find it again.</div>
      </div>
    </blockquote>
    <br>
    Yes, but also: everyone here knows about this risk.  You don't need
    to belabor the example :)<br>
    <br>
    This is a reflection of a problem we already have: equals is a
    semantic part of the type's definition, about when two instances
    represent the "same" value, and mutability is pat of the type's
    definition, and "whether you put it in a hash-based collection and
    then mutate it" is about _how the instances are used by clients_.  <br>
    <br>
    While immutability is a good default, its not always _wrong_ to use
    mutability; its just riskier.  And for a mutable class, state-based
    equality is _still_ a sensible possible implementation of equality;
    its just riskier.  And putting mutable objects in hash-based
    collections is also not wrong; its just riskier.  For the bad thing
    to happen, all of these have to happen _and then it has to be
    mutated_.  But if we have to assign primary blame here, it is not
    the guy who didn't write `final` on the fields, and not the guy who
    said that equality was state-based, but the guy who put it in the
    collection and mutated it.  <br>
    <br>
    If we decided that avoiding this risk were the primary design goal,
    then we would have to either disallow mutable fields, or change the
    way we define the default equals/hashCode behavior.  Potentially
    ways to do the latter include:<br>
    <br>
     - never provide a default implementation, inherit the object
    default<br>
     - don't provide a default implementation if there are any mutable
    fields<br>
     - leave mutable fields out of the default implementation, but use
    the other fields<br>
    <br>
    While "disallow mutable fields" is a potentially principled answer,
    it is pretty restrictive.  Of the others, I claim that the proposed
    behavior is better than any of them.  <br>
    <br>
    Carrier classes are about data, and come with a semantic claim: that
    the state description is a complete, canonical description of the
    state.  It seems pretty questionable then to use identity equality
    for such a class.  But the other two alternatives listed are both
    some form of "action at a distance", harder to keep track of, are
    still only guesses at what the user actually wants.  The two
    principled options are "don't provide equals/hashCode", and
    "state-based equals/hashCode", and of the two, the latter makes much
    more sense.<br>
    <br>
    It is not a bug to put a mutable object in a HashSet; it is a bug to
    do that _and_ to later mutate it.  So detuning the semantics of
    carriers, from something simple and principled to something
    complicated and which is just a guess about what the user really
    wants, just because someone might do two things that are each
    individually OK but together not OK, seems like an over-rotation.  <br>
    <br>
    <blockquote type="cite" cite="mid:1085557496.17567763.1768646213005.JavaMail.zimbra@univ-eiffel.fr">
      <div style="font-family: arial, helvetica, sans-serif; font-size: 12pt; color: #000000">
        <div>So I disagree that the component can be non final and that
          the class can be non final (you need those two to be
          non-modifiable).</div>
      </div>
    </blockquote>
    <br>
    For your code, sure.  And for mine, most of the time.  But you are
    saying that "no one should be allowed to have mutable carriers"?  <br>
    <br>
    <blockquote type="cite" cite="mid:1085557496.17567763.1768646213005.JavaMail.zimbra@univ-eiffel.fr">
      <div style="font-family: arial, helvetica, sans-serif; font-size: 12pt; color: #000000">
        <div>As Ganapathi Vara Prasad said, maybe you want the reverse
          semantics, instead of indicating the components, you may want
          to indicate the non-component fields, the derived fields. But
          for me, it does not seems useful enough.</div>
      </div>
    </blockquote>
    <br>
    This proposal seemed more about code golf?<br>
    <br>
    <blockquote type="cite" cite="mid:1085557496.17567763.1768646213005.JavaMail.zimbra@univ-eiffel.fr">
      <div style="font-family: arial, helvetica, sans-serif; font-size: 12pt; color: #000000">
        <div>A de-constructor becomes an instance method that must
          return a carrier class/carrier interface, a type that has the
          information to be destructured and the structure has to match
          the one defined by the type.</div>
      </div>
    </blockquote>
    <br>
    Careful there.  A deconstructor is like a constructor; it applies to
    an instance, BUT it cannot be inherited.  It is not like an instance
    method.<br>
    <br>
    <br>
  </body>
</html>