Deconstructor (and pattern) overload selection

Robbe Pincket robbepincket at live.be
Mon Apr 1 19:53:52 UTC 2024


Brian Goetz <brian.goetz at oracle.com> 2024-04-01 16:34Z:

> [...]
>
>  - Concision.  If a fully-general constructor takes many parameters, but not all are essential to the use case, then the construction site becomes a site of accidental complexity.  Being able to handle common grouping of parameters simplifies use sites.
>
>  - Flexibility.  Related to the above, not only might the user not need to specify a given constructor parameter, but they want the flexibility of saying "let the implementation pick the best value".  Constructors with fewer parameters reserve more flexibility for the implementation.
>
>  - Alternative representations.  Some objects may take multiple representations as input, such as accepting a Date, a LocalDate, or a LocalDateTime.
>
> The first two cases are generally handled with "telescoping constructor nests", where we have:
>
>     Foo(A a)
>     Foo(A a, B b)
>     Foo(A a, B b, C d, D d)
>
> [...]
>
> The "Flexibility" requirement does not really apply to deconstructors; having a deconstructor that accepts additional bindings does not constrain anything, not in the same way as a constructor taking needlessly specific arguments.  Imagine if ArrayList had only constructors that take int (for array capacity); this is terrible for the constructor, because it forces a resource management decision onto users who will not likely make a very good decision, and one that is hard to change later, but pretty much harmless for deconstructors.
>
> The "Concision" requirement does not really apply as much to deconstructors as constructors; matching with `Foo(var a, _, _)` is not nearly as painful as invoking with lots of parameters, each of which require an explicit choice by the user.
>
> So the main reason for overloading deconstructors is to match representations with the constructor overloads -- but with a given "representation set", there probably does not need to be as many deconstructors as constructors.  What we really need is to match the "maximal" constructor in a telescoping nest with a corresponding deconstructor, or for a tree-shaped set, one for each "maximal" representation.
>
> So for a class with constructors
>
>     Foo()
>     Foo(A a)
>     Foo(A a, B B)
>     Foo(X x)
>     Foo(X x, Y y)
>
> we would want dtors for (A,B) and (X,Y), but don't really need the others.

Well that does depend on whether you are going to allow deconstructors to be not total. If they don't have to be total, the deconstructor `Foo(X x)` could be short for `Foo(X x, null)` if constructor `Foo(X x)` calls `Foo(x, null)`.
However, it would become more complex when `Foo(X x)` calls `Foo(x, Foo.DEFAULT_Y)`. Now the deconstructor `Foo(X x)` doesn't really have a longer form equivalent.

Kind regards
Robbe Pincket
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://mail.openjdk.org/pipermail/amber-spec-observers/attachments/20240401/0e1b8767/attachment-0001.htm>


More information about the amber-spec-observers mailing list