----- Mail original -----
> De: "Brian Goetz" <[email protected]>
> À: "Remi Forax" <[email protected]>
> Cc: "Guy Steele" <[email protected]>, "Alan Malloy" <[email protected]>,
> "amber-spec-experts"
> <[email protected]>
> Envoyé: Mardi 8 Septembre 2020 15:53:36
> Objet: Re: Is case var(var x, var y) a valid syntax ?
>> - Is either total or partial. Deconstruction patterns are total; other
>> patterns
>> we'll be able to express later, such as `Optional.of(var x)`, are partial.
>
> While I don’t want to get into a deep dive on declared patterns now, let’s
> just
> say that they’ll exist and they’re important (Optional.of(var x),
> Optional.empty(), etc.) So in increasing order of generality:
>
> Type patterns: T t
> Deconstruction patterns: T(var x)
> Declared patterns: Optional.of(var x)
>
> Remi would like to view deconstruction patterns as a generalization of type
> pattern, but they are more properly understood as a restriction of declared
> patterns — just as constructors can be understood as a restriction of methods.
> Because we haven’t seen much of declared patterns yet, it is easier to miss
> their role in the spectrum, but their role is pretty obvious once you step
> back
> and think about it.
see below
>
> Deconstruction patterns are constrained compared to declared patterns in:
>
> - their name (like constructors!)
> - They are total on their declaring class, so they are guaranteed to match
> (much
> like a constructor is guaranteed to not return null)
> - While instance members, they are not inherited (just like constructors)
At least you want a deconstructor to be overrideable (which is not fully
equivalent to being inherited).
A deconstructor is for allowing encapsulation so the world projected by a
deconstructor may have a little to share with how the the class are implemented
class Employee {
int baseSalary;
deconstructor Employee(int salary) { return (baseSalary); }
}
class VP extends Employee {
int bonus;
deconstructor VP(int salary) { return (baseSalary + bonus); }
}
...
Vp vp = new VP();
vp.setBaseSalary(2000);
vp.setBonus(500);
Employee employee = vp;
employee instanceof Employee(salary) {
System.out.println(salary); // 2500
}
and here you can see that Employee(salary) is not a call to the deconstructor
but an instanceof Employee + a call to the deconstructor (int salary) !
> - They can only be called via a pattern match (just as a constructor can only
> be
> called via a `new` operation.)
so unlike a constructor that can be called either by a new or by this(...) and
super(...) a deconstructor can only be called vua pattern matching.
>
> The role of a constructor is to take an external state description, validate
> and
> normalize it, and produce an instance.
The role of a constructor is to hide the information of how a class is
implemented. Only if all the fields are final it plays the role of the single
gated entry point.
> The role of a deconstructor is to take an instance and produce an external
> state
> description. (If the ctor has to copy mutable elements on the way in, the
> dtor
> is also likely to want to do the same on the way out.)
The role of a deconstructor is to hide the information of how the class is
implemented and allow to pattern match to a projected form of the instance.
>
> In this way, both ctor and dtor mediate access between an external API and the
> internal representation.
It's only true for a constructor if the constructor (constructors) are the only
way to change the value of an instance.
It's only true for a deconstructor if the deconstructor has a matching
constructor
I start to think that calling a deconstructor a deconstructor is not the right
term because while a constructor and a deconstructor can be dual of each other,
this mirroring in not true in the general case,
it's only guarantee in the case of record because you have a canonical
constructor.
Rémi