Do non-member functions improve encapsulation in D?

Steven Schveighoffer via Digitalmars-d digitalmars-d at puremagic.com
Mon Apr 21 07:10:08 PDT 2014


On Mon, 21 Apr 2014 09:46:18 -0400, Lars T. Kyllingstad  
<public at kyllingen.net> wrote:

> On Monday, 21 April 2014 at 12:45:12 UTC, Steven Schveighoffer wrote:
>> 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.

Demonstration:

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!

>
>> 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().

It's the same (though not quite as important) as choosing a good name for  
a function.

-Steve


More information about the Digitalmars-d mailing list