digitalmars.D - Private and Package dynamic dispatch,
- Andrej Mitrovic (48/48) Mar 30 2013 A few months ago I posted this:
A few months ago I posted this: http://forum.dlang.org/thread/mailman.1030.1360125437.22503.digitalmars-d puremagic.com And this wiki page: http://wiki.dlang.org/Dispatching_an_object_based_on_its_dynamic_type But now I've implemented a similar feature for class methods. Let's say you have a class hierarchy in your library and you want to use virtual methods to implement specific functionality for each class. However you have one requirement: the user should not have access to these methods because they're supposed to be internal to the library. For one example, they might be needed to initialize some state based on the dynamic type before actually calling some public virtual method. Herein lies the problem, because you cannot have virtual private or package methods. But thanks to D's metaprogramming abilities you can dispatch to the appropriate private or package methods based on the dynamic type of the object, and this can all be abstracted away with a single D template. All the user has to do is: 1) Instantiate the magical template in module-scope (you'll see why this is important in a second), and pass leaf class types so the entire class hierarchy is registered with the template. 2) When invoking class methods, prepend "dynamic" to the call. The name of this magic namespace can be chosen by the user based on the template instance in step 1. 3) There is no step 3! Here's what typical user-code looks like at the call site: class A { private void foo(int x) { writefln("A.foo: %s", x); } } class B : A { private void foo(int x) { writefln("B.foo: %s", x); } } class C : B { private void foo(int x) { writefln("C.foo: %s", x); } } class D : B { private void foo(int x) { writefln("D.foo: %s", x); } } class E : B { } // pass leaf class types so they can be registered alias DynamicDispatch!(C, D, E) dynamic; void main() { A a = new A; A b = new B; A c = new C; A d = new D; A e = new E; a.dynamic.foo(1); b.dynamic.foo(1); c.dynamic.foo(1); d.dynamic.foo(1); e.dynamic.foo(1); } Thanks to UFCS the API itself is extremely easy to use. The full implementation: http://dpaste.dzfl.pl/08278225
Mar 30 2013