Private Interface

CategoryPattern: A StructuralPattern? 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 JamesNewkirk. Submitted to PLoP97 (PatternLanguagesOfProgramDesign), but not included in the volume three book.

Available at in the publications section

In the guise of PartialRevelation?, this was one of the interesting features of ModulaThree. 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 GarbageCollected 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 
      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.


  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( ... ) { ... } }
-- NatPryce

View edit of January 10, 2014 or FindPage with title or text search