Genericity and Virtual Types (VTs),
design patterns, and frameworks

1. Introduction

Design patterns [8] *) and frameworks are frequently represented by groups of cooperating, interdependent classes that reference each other and that have to be specialized/derived collectively in a consistent way in order to be used in actual applications. The term "framework" refers to the overall, top-level structure of entire applications while "design patterns" may also deal with groups of lower-level interdependent "generic utility classes" that may be specialized for concrete usage. Although the definition of design patterns would be given in natural language, perhaps enhanced by sketchy sample programs in a concrete programming language, it would be highly desirable to provide immediately reusable versions of design patterns in concrete programming languages like Lava.

The widespread programming languages, however, do not provide proper expressive means for implementing concrete incarnations of design patterns. Parameterized classes as the "templates" of C++ or the "generic classes" of Eiffel do not meet the requirements: They can be viewed as special macros or as type generation constructs having three serious drawbacks:

  1. They do not properly describe parameterized groups of interdependent classes but mainly single parameterized classes.
  2. They do not provide a derivation mechanism that allows you to derive specialized classes from those parameterized templates or generic classes.
  3. The older implementation techniques (C++) entail code replication rather than code reuse and thus are prone to blow up the program sizes as well as the time required for compilation/linking.

For the design of Lava we have drawn the following conclusions from this situation and from the fact that we have a package notion in Lava anyway that allows us to form groups of related classes or other declarations:

  1. Lava introduces patterns as packages or classes with named type parameters ("pattern parameters" or "virtual types", short: VT). Packages/classes with VTs are called "patterns" since they are used to provide concrete implementations of design patterns in Lava.
  2. The value of a VT may designate a Lava class or another VT that is visible at this place (see 8. below). A VT of a class may in particular designate its containing class and serve as a Lava substitute for the ThisType or MyType of other VT proposals.
  3. A virtual type may also be "abstract". Then its value is "void"; a non-void value may be assigned when overriding the abstract VT in a derived pattern.
  4. A VT v of a package/class P1 may be overridden in a derived package/class P2 by assigning a new value nv to it, which has to be derived from the value of v in the base package/class (except if v is abstract there). To override v you select it in the override view of P2 and proceed as described in the pertinent section.
  5. If a class A is declared within a pattern P then it can be extended only within P or within patterns derived from P.

    (This condition could possibly be weakened, but that would complicate the implementation as well as the rules that have to be obeyed by the programmers. The present wording just reflects the fact that the values of the VTs that may be referenced in A or its extension are defined only within P or patterns derived from P.)
  6. Classes from more derived patterns cannot be used in base patterns.
  7. VTs may be used to declare the types of local and member variables as well as of function arguments : Their actual, concrete types depend on the respective "pattern context" (see also 10. below). In the literature this is called "covariant specialization".
  8. The "visibility" of VTs is restricted in the following way: They are visible in the containing package or class where they are introduced. If they are visible in a class A then also in every nested declaration and in every implementation of A. If they are visible in a class or package P then also in every class/package derived from P unless they are overridden there. Classes declared in a pattern P' that is derived from P cannot be referenced in P.
  9. If a class A is the value of a virtual type V then A cannot also be the value of another virtual type. (A motivation of this rule is given in our IsSelfVirtual sample.)
  10. Lava restricts the ways in which pattern declarations may be nested: There may be only two nested layers of packages or classes containing virtual types. (The VT implementation costs would be considerably higher if nesting of VT layers to any depth would be allowed.) The lower layer is called the "inner pattern context", the higher one the "outer pattern context" of the declarations belonging to or nested in the lower layer. Generally, the term "pattern context of a declaration" designates the combination of the inner and outer pattern context.
  11. Lava supports multiple inheritance not only on the class level but also on the package level: A package may be derived from one or several other packages. Non-overridden virtual types from immediate or indirect base patterns are inherited and visible also in the derived pattern.
  12. If a pattern P1 references a type T2 that is the value of a virtual type of a separate pattern P2 and a third pattern P3 is derived from P1 and P2, then the reference to T2 is still treated as an "external" rather than as a virtual type reference (although T2 belongs to the context of the common derived pattern P3 now).
  13. Lava maintains the classical view of parameterized types (like C++ templates) insofar as it considers two instantiations of the same type in different pattern contexts to be incompatible.

The currently valid value of a pattern parameter or "virtual type (VT)" is taken at run time from a "virtual type table (VTT)" similar to the usual "virtual function table (VFT)" of object-oriented programming systems. As usual, Lava provides for every Lava object a pointer to its associated VFT, but additionally also a pointer to an associated VTT. Like the VFT, the proper VTT is determined on object creation, roughly spoken as the "pattern context" of its implementation, and this is in turn the pattern context of the class that the latter implements.

Generally, we use the term type for a concrete class or a virtual type / pattern parameter in the sense explained above. (Both may be referenced as types of variables in Lava programs.)

A type is called a multiform type if it is either a virtual type or a class that is declared within a pattern. The structure and meaning of a multiform type may depend on the pattern context where it is used. We use "uniform" as a synonym for "non-multiform".

Virtual types may be referenced anywhere (on any nesting level) within their "owner" package or class, but also in implementations of classes belonging to that scope. (These implementations may be located even outside this scope.)

Summary: A Lava pattern is just a quite normal package or class declaration, having virtual types.

2. Representation and specialization of patterns in LavaPE

In the Lava declaration view a pattern is just a quite normal package or class declaration, having virtual types (VT). A virtual type vt has a name and a value VAL(vt). The value may be a class (having the name of the virtual type) or the name of another VT. (The term "bound" is also used in the literature for the value of a VT.)

A virtual type may also be "abstract". Then its value is "empty"; a non-empty value may be assigned when overriding the abstract VT in a derived pattern.

A VT is called "final" if its value is a class. This class cannot be referenced then as a normal class within the containing pattern; its name rather denotes the VT whose value it is. Outside the pattern, it denotes just the class.

Moreover, classes (and virtual types anyway) of a derived pattern P cannot be referenced in base patterns of P.

A VT has a name and a value. The value may be (the name of) a class or of another VT. A virtual type may also be "abstract". Then its value is "empty"; a non-empty value may be assigned when overriding the abstract VT in a derived pattern.

Generally, package and class declarations may be nested to any depth in Lava (but class declarations cannot contain nested package declarations). For packages and classes with virtual types the above-mentioned restrictions apply, however.

Specialization of patterns makes use of the same Lava override view that is also used for quite normal class derivation.

3. Static type-safety of Lava, related work

A special section of this documentation has been dedicated to the static type-safety of Lava. The relation of our approach to other notions of virtual types is discussed here. An outline of the proof of the static type-safety of Lava can be found at the same place.

See also:

Patterns and type casts

Pattern samples