Do non-member functions improve encapsulation in D?
Lars T. Kyllingstad via Digitalmars-d
digitalmars-d at puremagic.com
Mon Apr 21 06:46:18 PDT 2014
On Monday, 21 April 2014 at 12:45:12 UTC, Steven Schveighoffer
wrote:
> [...]
>
> Reasons off the top of my head not to make them module
> functions:
>
> 1. You can import individual symbols from modules. i.e.:
>
> import mymodule: MyType;
>
> If a large portion of your API is module-level functions, this
> means you have to either import the whole module, or the
> individual methods you plan to use.
Based on this, combined with your points 6 and 3 further down --
the second number 3, that is :) -- we can make the following
guideline:
Methods which are central to the class' usage, and which are
therefore likely to be used often, should be member functions,
while auxiliary functions and convenience functions should be
non-members.
The same thing was stated earlier in this thread, in different
words, and I guess it is the rule most of us use already.
However, this is the first non-subjective rationale I've seen for
it so far. Awesome!
> 2. You can get delegates to methods. You cannot get delegates
> to module functions, even if they are UFCS compatible.
This is an excellent point. I would never have thought of that.
> 3. There is zero chance of a conflict with another type's
> similarly named method.
How? If you have the following functions:
void foo(A a);
void foo(B b);
and you write
foo(new B);
there is also zero chance of conflict -- even if B happens to be
a subclass of A, since the most specialised function is always
called.
> 4. It enforces the "method call" syntax. I.e. you cannot use
> foo(obj) call. This may be important for readability.
Some would argue that giving users the choice between typing
foo(obj) and obj.foo() is a Good Thing, because it doesn't impose
your preferences on them. I'm not going to do that, though. ;)
> 5. You can only use operator overloads via methods. D is
> different in this respect from C++.
True. Operator overloads fall in the same category as virtuals
and interface functions, i.e., the ones that *cannot* be
non-members.
> [...]
>
> Reasons to make them module functions:
>
> 1. You have more than one object in the same file which
> implements the method identically via duck typing.
>
> 2. You want to change how the 'this' type is passed -- in other
> words, you want to pass a struct by value or by pointer instead
> of by ref.
>
> 3. The complement to #1 in the 'against' list -- you want your
> module-level API to be selectively enabled!
>
> 4. Of course, if you are actually implementing in a different
> module, Scott Meyers' reasoning applies there.
All very good points. This is exactly what I was looking for,
thanks!
More information about the Digitalmars-d
mailing list