Thread overview
Rethink OOP access permissions
Apr 27
Daniel N
Apr 28
Daniel N
Apr 28
Daniel N
Apr 30
Dom DiSc
April 27

This is an alternative to "private(this)".

I think it would be much more interesting if it was possible to separate read and write permissions instead.
(The syntax is just an example, not that important, just for illustration purposes.)

class C
{
    get(module) set(class) int x = 0;
}

Some ideas from C# are also interesting. They have 'init' and 'readonly' aswell.

https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/proposals/csharp-9.0/init

struct Point
{
    public int X { get; init; }
    public int Y { get; init; }
    public readonly int Z { get; init; }
}

Instead of trying to cater to a single usecase ("private(this)"). We could get unix like access permissions instead? Some additional benefits would be fast access to read-only variables instead of an expensive function call.

April 28
On 27/04/2024 9:25 PM, Daniel N wrote:
> This is an alternative to "private(this)".
> 
> I think it would be much more interesting if it was possible to separate read and write permissions instead.
> (The syntax is just an example, not that important, just for illustration purposes.)
> 
> ```d
> class C
> {
>      get(module) set(class) int x = 0;
> }
> ```

While I'm not against it, think about how this would be implemented.

You would need an enum with all the different values for both getting and setting, I can already see some resistance there.

Plus you'd need some arithmetic on the values, to see if you can perform operators (modify in place).

> Some ideas from C# are also interesting. They have 'init' and 'readonly' aswell.

The C# ``readonly`` type qualifier is similar to our ``immutable``, this comes from Midori and one of the language authors Joe Duffy has compared it equivalently against D's previously.

April 28
On Saturday, 27 April 2024 at 09:25:13 UTC, Daniel N wrote:
> This is an alternative to "private(this)".
> ..

private(this) is trying a very specific problem - that can be demonstrated in the contrived code further below.

That is, anyone other than the author will not know whether a mistake is in this code.

Maybe even the author will miss it ;-(

If there is a mistake, the compiler will be of no help here.

But what is certain, most programmers who look at this code will not know whether a mistake is being made or not. And it precisely because oop in D is really mop (module-oriented-programming).

D does however, provide a means to illude oo programmers into thinking they're doing oop, if they put each class in its own module, with no other code whatsoever. This makes the type a strong type, with compiler enforced guarantees, and it gives you the illusion that you're doing oop.

But there is no more easier to grasp, easier to implement solution here, other than private(this).

D claims to support oop, but when you really look into it, it's really mop, with the silly burden it places on you, that you have to put a class in its own module if your want oop like guarantees.

How would your alterative compare to private(this) in the code below?

class ClassWithPrivateField
{
  private int privateField; // actually, I really wanted to do 'private(this)' here.
  this() { this.privateField = 42;  }
}

class Subclass : ClassWithPrivateField
{
  private int subPrivateField;

  this()
  {
    this.subPrivateField = 23;
    this.privateField = 52; // mmm .. this may or may not be a mistake.
                            // without private(this) you cannot know.
                            // you could use convention, but we all know
                            // how well that scales ;-)
  }
}

April 28

On Sunday, 28 April 2024 at 02:43:21 UTC, NotYouAgain wrote:

>

On Saturday, 27 April 2024 at 09:25:13 UTC, Daniel N wrote:

>

This is an alternative to "private(this)".
..

How would your alterative compare to private(this) in the code below?

class ClassWithPrivateField
{
private int privateField; // actually, I really wanted to do 'private(this)' here.
this() { this.privateField = 42; }
}

class Subclass : ClassWithPrivateField
{
private int subPrivateField;

this()
{
this.subPrivateField = 23;
this.privateField = 52; // mmm .. this may or may not be a mistake.
// without private(this) you cannot know.
// you could use convention, but we all know
// how well that scales ;-)
}
}

I'm the first to admit the syntax of my proposal needs work, but I just wanted to get the discussion going.

get(class) set(class) int privateField; // equivalent with private(this)

By solving more than one usecase, the feature might appeal to more people.

April 28
On Sunday, 28 April 2024 at 07:30:13 UTC, Daniel N wrote:
>
> By solving more than one usecase, the feature might appeal to more people.

fair enough.

Perhaps we need both private(this) and protected(this).

This unittest below will pass, but it really should not.

That's because not just private, but also protected, is public inside the module.

It one really must put one class in a module, and unittests in their own module as well,
just to get the assurances of correctness, that other languages can already provide.

D really is module-oriented-programming, not object-oriented-programming.

module m;

unittest
{
   import std;

   ColoredPoint c = new ColoredPoint(2, 4);

   writefln("%s : %s", c.x, c.y); // 2 : 4

   c.reset(); // actually this shouldn't even be allowed. It is not in the intent of the design.
   c.clear(); // only the clear() method should be using reset()

   writefln("%s : %s", c.x, c.y); // 0 : 0

}

// Based on some code from: https://docs.oracle.com/javase/specs/jls/se22/html/jls-8.html
// I've change a few things though.

class Point
{
  private int x, y;

  this(int x, int y)
  {
      this.x = x;
      this.y = y;
  };

  protected void reset() { this.x = 0; this.y = 0; } // In D, protected means accessible to subclass,
                                                     // and ALL other code within the module!
                                                     // But clearly the intent here is for only the sublcass to access it
                                                     // via it's public clear() method - which calls its base reset() method.
                                                     // Other code in the module should not be accessing this reset() method.
                                                     // But there is no way in D to express that intent.
}

class ColoredPoint : Point
{
    this(int x, int y)
    {
        super(x, y);
    };

    void clear() { reset(); }
}

April 28
On Saturday, 27 April 2024 at 12:37:14 UTC, Richard (Rikki) Andrew Cattermole wrote:
> On 27/04/2024 9:25 PM, Daniel N wrote:
>> This is an alternative to "private(this)".
>> 
>> I think it would be much more interesting if it was possible to separate read and write permissions instead.
>> (The syntax is just an example, not that important, just for illustration purposes.)
>> 
>> ```d
>> class C
>> {
>>      get(module) set(class) int x = 0;
>> }
>> ```
>
> While I'm not against it, think about how this would be implemented.
>
> You would need an enum with all the different values for both getting and setting, I can already see some resistance there.
>
> Plus you'd need some arithmetic on the values, to see if you can perform operators (modify in place).
>

You're right, it's not easy, but it could be simplified using bitfields instead of enums.

April 30
On Sunday, 28 April 2024 at 08:15:14 UTC, NotYouAgain wrote:
> This unittest below will pass, but it really should not.

There you have a point.
Most of the time I like to be able to use private stuff in my unit-tests (white-box tests), but if the purpose of the test is to check for correct encapsulation (black-box tests), then it must not have access to this.

On the other hand, one could argue that black-box tests _need_ to be in a different module, because else it's not a black-box to them anymore (writing a black-box test shall not modify the subject under test - which is impossible if it is in the same file).