`restricted` member variables

Paul Backus snarwin at gmail.com
Thu Jun 23 01:45:22 UTC 2022


On Thursday, 23 June 2022 at 01:27:23 UTC, Mike Parker wrote:
> A class in its own module can fully maintain its invariants, 
> even when multiple methods modify a variable. Every function 
> call is bookended with the invariant check.
>
> There's a hole in module scope in that we treat modules as part 
> of the aggregate's private API, but not as part of the public 
> API. A new level of protection wouldn't fully plug that hole, 
> but running invariant checks on access to private member 
> variables from within the module would.
>
> This whole discussion has led me to the opinion that if a 
> module is part of the private API, then we ought to be treating 
> it as part of the public API in terms of invariant and 
> synchronized.

Your proposal would lead to the following situation:

     struct EvenNumber
     {
         private int n;
         invariant (n & 1 == 0);

         this(int n) { this.n = n; }

         void addTwoMethod() { this.n++; this.n++; } // ok
     }

     void addTwoUFCS(ref EvenNumber this_)
     {
         this_.n++; this_.n++; // error - violates invariant
     }

IMO the correct way to view this is that code in the same module 
as a class is part of the class's implementation, just as much as 
code in the actual class body. (Or if you prefer, they are both 
part of the module's implementation, since the module is the 
fundamental unit of decomposition here, not the class.)

Note that sometimes, one is actually required to implement 
methods as UFCS functions rather than actual aggregate 
members--for example, to work around issue 5710 [1], or if one 
wants to write a struct method that takes its "this" argument by 
value instead of by reference.

[1] https://issues.dlang.org/show_bug.cgi?id=5710


More information about the Digitalmars-d mailing list