Quantcast
Channel: D Bits
Viewing all articles
Browse latest Browse all 13

Extended Package Protection in D

$
0
0

Since the D1 days, D has a had a package protection attribute akin to Java's (though unlike Java, it is not the default). Applying package attribute to any symbol in a module makes it accessible only to modules in the same package.

module mylib.mypackage.mymodule;

package struct MyStruct {...}

class MyClass {
   package void doSomething() {...}
}
Given the above, MyStruct is only usable and the member function doSomething in MyClass only callable directly inside the mylib.mypackage package. However, neither is accessible in any subpackages of mypackage (such as in a module mylib.mypackage.subpack.somemodule).

 

There was some demand for expanding the scope of package protection, so it was eventually added to the language. The above code still works as it always had, restricting access exclusively to the package in which a symbol is declared. Now, it's possible to do something like this:

module mylib.mypackage.mymodule;

package(mylib) MyStruct { ... }

class MyClass {
   package(mylib.mypackage) void doSomething() {...}
}
In this snippet, MyStruct is accessible in the mylib package and all of its subpackages. The doSomething member function of MyClass is callable in mylib.mypackage and all of its subpackages. In effect, specifying a package name with the attribute tells the compiler the topmost package in which a symbol should be accessible, making it accessible also to all subpackages of that package.

 

This isn't an earth shattering feature, but it allows much more freedom for code organization. Consider a renderer package for a 2D or 3D game engine. One possible approach to supporting multiple renderers is to have a base engine.gfx package which contains the interfaces and an engine.gfx.impl package for all of the implementations (e.g. engine.gfx.impl.ogl). The extended package protection comes in handy here to make common internal declarations visible to the implementations while hiding them from the outside world:

module engine.gfx.common;

package(engine.gfx):

enum internalConstant = 123;

struct InternalStruct { ... }

void internalFunction() { ... }
Previously, you might put this module in the engine.gfx.impl package, make everything public, and tell users not to import anything in the impl package as a form of voluntary protection. Now, you don't even need a 'common' module. You can put each declaration where it makes sense to put it and the compiler will enforce your protection scheme for you.

Viewing all articles
Browse latest Browse all 13

Latest Images

Trending Articles





Latest Images