Private Interface

Category Pattern: A Structural Pattern that "provides a mechanism allowing specific classes to use a non-public subset of a class interface without inadvertently increasing the visibility of any hidden member variables or member functions". In other words, how to give another class access to some of your "private" functions, without making them a "friend".

By James Newkirk. Submitted to PLoP97 (Pattern Languages Of Program Design), but not included in the volume three book.

Available at www.objectmentor.com in the publications section


In the guise of Partial Revelation, this was one of the interesting features of Modula Three. In M3, a type definition could be divided up into a set of interfaces which are eventually combined to make up the type. How much of the type you can see depends on which interfaces you have imported into your compilation unit. It's really neat for providing controlled access to a library, for example: to distinguish between those parts of an implementation which are Garbage Collected and those parts that aren't and have to be looked after.


The implementation of this in C++ is beautiful. I've used this when I want to make a C++ class an observer, but I don't want other users of the class to have access to the callbacks. It goes like this (from memory):

class Observer { public: void callback (...) = 0; }

class Observable { public: void registerObserver (Observer * o); } class My_Observer : private Observer { public: My_Observer (Observable & observable) { observable.registerObserver (this); } private: void callback (...); }

At first glance, it seems odd that the language will let you pass this to a function expecting a class from which this is privately derived. After all, private derivation means "is not a". But it turns out that the language explicitly allows this: Members and friends of a class X can implicitly convert an X* to a pointer to a private immediate base class of X. (ARM 11.2)


The Java equivalent is to implement private interfaces as an (anonymous) inner classes, because Java only allows public interface inheritance.

E.g.

interface Observer { void callback( ... ); }

interface Observable { void registerObserver( Observer o ); } class My_Observer { public My_Observer( final Observable observable ) { observable.registerObserver( new Observer() { public callback( ... ) { observableCallback( ... ); } } ); } private void observableCallback( ... ) { ... } }

See original on c2.com