The Envelope-Letter Class Idiom


The technique used in this article is described in Coplien's excellent book [2]. The approach is called the envelope-letter class idiom, and is so named because one object contains, or "envelops" the entire public interface of another object.

This is actually achieved in the envelope class by maintaining a pointer to a letter object, and calling letter-class methods through this pointer. (This may also be accomplished with a reference instead of a pointer, but I chose a pointer for the classes in this article because I needed to be able to dynamically reassign this pointer after its initial assignment.)

Any class is capable of being a letter class; there are no special design requirements. This means that an envelope class can be a letter to some other envelope, giving a limitless depth of packaging. In this article, the pointer that is maintained in the envelope class is of the same type as the envelope class itself, so there is no distinction between envelope and letter. This allows objects to be linked together to any depth desired. (You might call it "chain mail.") The only limitation is that there has to be some substance — a real letter — at the base of the chain. After all, what good is it to receive a package that just contains boxes inside of boxes? In the innermost box, there would have to be some treasure that would justify all of this packaging! This is where the buffer classes, described in the article, come in. They hold the real data of the chain.

The effect of all of these envelopes holding envelopes holding more envelopes, and so on, is what can loosely be called "dynamic inheritance." Each envelope inherits properties from the previous envelope in the chain, by calling methods in the previous envelope.

You must consider the performance tradeoffs when using dynamic inheritance. Each object in the chain must reference the previous object in the chain, which at the very least requires dereferencing a pointer. In addition, the class is probably doing some sort of manipulation of the data in the letter class (else there would be no need for the extra link in the chain). For this reason, it may make sense to make more of the objects buffer-carrying envelopes, to avoid referencing the previous object in the chain for every data access. This is discussed further in the accompanying article.