Choosing an interpreter


introduction framework patterns components conclusions references appendix experience
The envelope/letter idiom (originally introduced in  [Coplien] is increasingly adopted as a standard approach to separate the definition of a high level interface and its realization by an implementation class. Usually, this involves two classes, say an abstract class A and its implementation class AImpl. A disadvantage of this approach is that an additional (implementation class) is added to the class (name) space. Another disadvantage is that refining the behavior of a class using inheritance becomes more cumbersome.

To illustrate our approach, look at the definition of the class kit:

  class kit {
  public:
    kit( char* kind = "tcl" );

    virtual int eval(char* cmd) { return _kit?_kit->eval(cmd):0; }
    ...
  protected:
    kit( kit* );
    kit* _kit;
  };
The constructor of kit indicates as a default a Tcl interpreter which is encapsulated by the class:
  class tcl_kit : public kit {
  public:
    tcl_kit() : kit(0) { ... }
    ...
  };
The constructor of kit assigns the tcl_kit instance to its _kit variable. In contrast, the tcl_kit initializes its (parent) _kit variable to zero. For the kit instance created by the user, calls are delegated to the tcl_kit instance. However, the user may still inherit from kit and selectively override its functions.
introduction framework patterns components conclusions references appendix experience