Non-ugly ways to implement a 'static' class or namespace?
Mike Parker
aldacron at gmail.com
Wed Feb 15 08:56:00 UTC 2023
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.
More information about the Digitalmars-d-learn
mailing list