Extending D's support for object-oriented design with private(this)
NotYouAgain
NotYouAgain at gmail.com
Thu Apr 25 05:37:24 UTC 2024
TITLE: Extending D's support for object-oriented design with
private(this)
NOTE: Only civil and well-informed discourse on this idea is
welcome.
DIP forum guidelines are here:
https://github.com/dlang/DIPs/blob/master/docs/guidelines-forums.md
BEGIN:
This DIP idea, relates to extending D's support for
object-oriented design - by allowing private visibility to be
attached to a class member.
The proposal creates no new limitations and no code breakage.
BACKGROUND:
The class type is the core building-block of class-based
object-oriented design.
The facility for abstract, structured reasoning about a class
type comes from its support for encapsulation.
D provides a class type, which in turn allows D to support
class-based object-oriented design, with encapsulation,
inheritance, and polymorphism.
see: https://dlang.org/spec/class.html
However, D's minimal encapsulation unit is actually a module, not
a class.
That is, class private members are actually private module
members, not private class members.
Although private class members cannot be interacted with from
another module, they can be interacted with using code inside the
same module (but outside of that class).
That's because (in D) the module, not the class, is the
encapsulation unit.
Example (code in the same module - but outside of the class
definition - accessing a private class member):
// --
module m;
class C
{
private int _count; // visibilty of this member extends to
the entire module.
}
unittest
{
C c = new C();
c._count = 42;
}
// ----
D also provides another form of encapsulation for 'a set of
modules', when those modules all belong to the same package.
As such, a private class member cannot be interacted with from
other modules that don't belong to the same package, but can be
interacted with using code inside any of
the modules belonging to that package.
D's insistance (and apparent zealous protection) for having the
module as the minimal encapsulation unit, is inconsistent with
object-oriented design, where the class is itself a unit of
encapsulation.
This has the following consequences:
(1) It makes it difficult to reason about a class definition in a
module, when there is other code in the module, as all other code
in the module is in essence a part of the class definition.
(2) It allows for accidental, unintended use of a private member
by other code in the module, including unittests.
// --
module m;
class C
{
private int _count; // visibilty of this member extends to
the entire module.
public void setCount(int c) { _count = c; }
}
unittest
{
C c = new C();
c._count = 42; // Actually, this is a mistake, and the
programmer should be testing the public method setCount(..)
}
// ----
(3) One can only 'simulate' class-based encpasulation in D, by
putting each class in its own module. This is, apparently, what
is recommended whenever this topic is raised in the forums.
Both (1) (2) (3) can be fully resolved by adding private(this)
functionality, as demonstrated here:
// --
module m;
class C
{
private(this) int _count; // visibilty of this member is
contained within this type
}
unittest
{
C c = new C();
c._count = 42; // Error: data member _count is an
inaccessible (private)property of type `m.C`
}
// ----
More information about the dip.ideas
mailing list