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 http://www.objectmentor.com 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.

See http://www.research.digital.com/SRC/modula-3/html/partial-rev/index.html


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

EditText of this page (last edited January 10, 2014) or FindPage with title or text search