Do non-member functions improve encapsulation in D?

Lars T. Kyllingstad via Digitalmars-d digitalmars-d at puremagic.com
Mon Apr 21 07:38:51 PDT 2014


On Monday, 21 April 2014 at 14:10:08 UTC, Steven Schveighoffer 
wrote:
> [...]
>
> module m1;
> import std.stdio;
>
> class C {}
>
> void foo(C c)
> {
>    writeln("C.foo");
> }
>
> void bar(C c)
> {
>    writeln("C.bar");
> }
>
> module m2;
> import m1;
> import std.stdio;
>
> void foo(T)(T t)
> {
>   writeln("m2.foo");
> }
>
> void bar(T)(T t, int x)
> {
>   writeln("m2.bar");
> }
>
> void main()
> {
>    auto c = new C;
>    c.foo(); // "m2.foo";
>    //c.bar(); // error if uncommented!
> }
>
> Basically, I've inadvertently overridden C.foo, without 
> intending to. With bar, I've somehow hidden the inherent 
> functionality of C!

Wow, I didn't know that.  I thought the most specialised function 
would always be selected, regardless of which module it's defined 
in.  What you've demonstrated feels wrong, somehow.

>>> 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. ;)
>
> You may recall that I am a big proponent of explicit properties 
> because I think the ways of calling functions have strong 
> implications to the reader, regardless of the functions. This 
> is the same thing. I look at foo(x) much differently than 
> x.foo().

And you may recall that I was on the same side as you in the 
properties debate, though less vocal about it.  (In fact, I think 
we didn't go far enough with properties -- we should also forbid 
taking their address.  But that's another discussion.)  The point 
is, I lean towards the same view as you when it comes to UFCS, 
and only brought up the opposing view for the sake of the 
discussion.

I tend to use UFCS only for a few select cases (array range 
functions, range chaining, etc.), and to otherwise use the 
"normal" function call syntax.  If someone sees this in my code:

   obj.foo();

I want them to know where to look for further information about 
foo(), namely in the class documentation/code.


More information about the Digitalmars-d mailing list