On 07/07/2014 09:44 PM, NoUseForAName wrote:
In C my favorite way of achieving encapsulation is to use incomplete
types. The module header contains the definition of an incomplete type
and the prototypes for the public functions which operate on it. I have
read D has incomplete types too however D does not have headers and as a
C guy I do not know how to implement this scheme without a .h/.c
separation.

As I said, in C I put the incomplete declaration in the header while
keeping the complete declaration private to the module. How do I do this
in D? I mean type is complete within the module itself (and thus can be
instantiated there) but incomplete for clients (i.e. other modules) i.e.
instantiating or modifying data of that type directly is impossible.

P.S.: It seems D lingo for incomplete types is "opaque types".

1) Put the opaque type and its functions into a .di file:

// deneme.di
module deneme;

struct S;

S * makeS(int i);

void useS(S * s);


2) Put the implementation in its .d file:

// deneme.d
module deneme;

import std.stdio;

struct S
{
    int i;

    void foo()
    {
        writefln("Executing foo() for %s", this);
    }
}

S * makeS(int i)
{
    return new S(i);
}

void useS(S * s)
{
    s.foo();
}


3) Compile the implementation as a library (just a .o in this case):

$ dmd deneme.d -c

(That will create the file deneme.o)


4) Write a client program that uses the interface. (Make sure that only deneme.di is visible to the client (not deneme.d).)

// main.c
import deneme;

void main()
{
    S * s = makeS(42);
    useS(s);
}


5) Compile (and link) the client program and the library to make the program:

$ dmd main.d deneme.o

(That will create the executable 'main'.)


6) Run the program:

$ ./main
Executing foo() for S(42)

Ali

Reply via email to