On Wednesday, 15 February 2023 at 07:23:39 UTC, thebluepandabear wrote:


Why is the unit of encapsulation the module though? Makes no sense.

What is the purpose of encapsulation? To keep the implementation details hidden behind the public API, such that changing the implementation doesn't change the API.

Consider this:

```d
module gfx;
struct Point {
    private int x, y;
    this(int x, int y)
    {
        this.x = x;
        this.y = y;
    }

    void move(Point to) {
        x = to.x;
        y = to.y;
    }
}
```
Here, `move` is part of the public API. `x` and `y` are part of the implementation. Nothing outside the module can touch them.

Now this:

```d
module gfx;
struct Point {
    private int x, y;
    this(int x, int y)
    {
        this.x = x;
        this.y = y;
    }
}

void move(ref Point from, Point to) {
    from.x = to.x;
    from.y = to.y;
}
```

From the perspective of the public API, nothing has changed. The following works in both cases:

```d
Point p;
p.move(Point(10, 20));
writeln(p);
```

In both cases, the implementation is hidden behind the same public API.

If private were restricted to the class/struct, it would add anything more for encapsulation in D. In practical terms, if you are editing the `gfx` module, you also have access to the implementation details of `Point`.

Sure, if you have e.g., a special setter that does some extra work when a member variable is set, you want to ensure that only that setter is used to change the member variable. But that's true *inside the class/struct* as well.

I mean, just consider this:

```d
class C {
    private enum minX = -100;
    private int _x;

    void setX(int newX) { _x = newX > minX ? newX : minX }

    void doSomething(State s) { setX(_x + s.val); }
}
```

vs. this:

```d
class C {
    private enum minX = -100;
    private int _x;

    void setX(int newX) { _x = newX > minX ? newX : minX }
}

void doSomething(C c, State s) { c.setX(c._x + s.val); }
```

Ideologically, they are not the same. In practical terms, they are. Whether the closing brace of the class declaration is before or after `doSomething` matters not one bit. Yes, things can go wonky in a module that's many lines long and someone sets `_x` from outside of the class. So what? The same is true for a class that's many lines long when someone adds a new method that directly sets `_x` rather than going through the setter.

D's modules are intended to be used for grouping related constructs. Everything in the module is part of the same private implementation. If the constructs aren't related, then put them in separate modules. And there's still a solution for anyone with a strict ideological preference regarding related constructs: they can put their classes and structs in individual modules under a common package. `package` protection can be used for cross-module access inside the package, and the entire set can be presented to the outside world as a single module with `package.d`.

Our friend of many forum handles misses no opportunity to return to this putrid horse corpse to beat it some more, but the meaning of private isn't going to change. This is D's approach to encapsulation.

Reply via email to