Basic virtual type samples

Sample files

Please open ChoralSociety.lava in LavaPE.

Please open ModelView.lava in LavaPE.

Please open QueueOfPoint.lava in LavaPE.

Please open Visitor.lava in LavaPE.

Please open FinalVirtualType.lava in LavaPE.

Please open FactoryForceOverride.lava in LavaPE.

Topic

Interfaces and packages with type parameters ("virtual types"), covariant specialization.

Overview

ChoralSociety:

The ChoralSociety sample provides a package S ("Society") with two virtual types society and member. In S the value of society is the type Society, the value of member is Member. A second package CS ("ChoralSociety") is derived from S by specializing society to become ChoralSociety (in turn derived fro Society) and member to become Singer (derived from Member). As a consequence, the MemberList becomes a list of Singers in CS automatically, and the chairman is also a Singer in CS rather than just a Member.

ModelView:

The ModelView sample (based on the well-known subject/observer pattern) reconstructs the corresponding sample from [16]. It provides a package ModelViewFW ("model/view framework") with two type parameters "model" and "view". "ModelViewFW" contains two mutually recursive types "Model" and "View". "Model" contains a member vList which is a homogeneous "ViewList" all of whose elements have the same virtual type setElem=~<view>. (The tilde "~" marks variable state objects in Lava.)

Package "DrawFW" shows how the (rudimentary) framework "ModelViewFW" could be specialized by overriding its virtual types (= type parameters) "model" and "view".

See our ModelManyViews sample for another variant of Model/View that provides an inhomogeneous "ViewList" containing different types of views (on the basis of "substitutable types").

QueueOfPoint:

The QueueOfPoint sample corresponds to a similar sample in [16], too. Compared to [16], it shows again the advantage of making virtual types non-substitutable by default: We need not view the virtual type "elemType" as a special, type-valued member variable of "Queue" objects but we can introduce virtual types in a more static way as type parameters of classes and packages.

Visitor:

The Visitor sample illustrates a special case of the well-known "Visitor" pattern of [8] and also a special case of indirect tree recursion.

FinalVirtualType and FactoryForceOverride:

There are situations where you want to assign an object of a concrete Lava class to a variable whose type is virtual, particularly if you create the object from scratch using the new expression of Lava. In the new expression you have to select one of the initializers of the respective Lava  class generally. But only concrete Lava  classes have initializers, virtual type parameters don't. Therfore you are not allowed to specify a virtual type as the type of the new object in the new expression, but only a concrete Lava  class.

The assignment "concrete to virtual type" can be made compatible in two ways in Lava

  1. Either you can assign the "force  override on derivation" attribute to a virtual function within whose body the "concrete to virtual type" assignment occurs and ensure in this way that this function is overriden in the derived class or pattern. This prevents the critical assignment from being taken over to the more derived context. The FactoryForceOverride sample presents a simplistic example of this kind.
  2. Or (since Lava  release 0.9.1) you can assign the "final" attribute to the virtual type in question and prevent it from being derived at all. The FinalVirtualType sample makes use of this method, based on the "final" attribute.

Where to look and what to do

ModelView:ew:

Note in particular the "covariant specialization" of the only input parameter of function registerView of class Model.

Note how this is exploited in the exec of the main program ModelViewDemo to pass a view object of the derived type DrawFW::View to this function.

Note that DrawFW::View is not compatible in the traditional sense (of c-derivation) to ModelViewFW::View, since it contains member variables (myModel) and function parameters (m of initializer ini) that are of a more derived type in pattern DrawFW than in ModelViewFW (as a consequence of covariant specialization of the VT <MODEL>).

QueueOfPoint:

Note the difference between the classes X_inner and X_outer: X_inner belongs to pattern Queue (a class having a VT elemType), whereas X_outer is declared outside class Queue. Both have a member function f with almost identical implementations. Look at these:

The difference between the implementations of the two versions of f is that one of them belongs to pattern Queue, and one doesn't. The former has to use the virtual type <Queue::elemType> of Queue to declare the local variable p, the latter cannot use this but must use the concrete class Point to declare p. The reasons are:

  1. If a class A is the value of a virtual type V then A cannot be referenced directly at any place where V is visible. It can only be referenced indirectly by references to V in these places. If A1 is derived from A within the same pattern, then A1 cannot be referenced directly, either.
  2. From outside a pattern the VTs of that pattern cannot be referenced (they are invisible to the "outside world").

The first rule corresponds to rule 9 in our Lava genericity section. Its motivation is explained in our IsSelfVirtual sample.

The reason for the validity of the second rule is simple: The value of a VT (= type parameter) is determined by the respective pattern context. So if you are outside a pattern P and outside of any pattern that is derived from P, the values of P's VTs at the actual place of reference are just undefined.

Visitor:

The Visitor pattern defines an abstract virtual type R for the result of the visitor's tree evaluation function evaluate. The way how the visitor walks through the tree is described by this evaluate method and doesn't depend on R, while the treatment of the individual tree nodes depends on R and is implemented by the overridden methods evalLeaf and evalNode of StringVisitor and IntVisitor. The initiator VisitorDemo shows how a sample tree is constructed and how this same tree is evaluated twice: once by the StringVisitor and once by the IntVisitor

Please note the comments in the VisitorDemo initiator.

FinalVirtualType:

Look into the property sheet of virtual type ELEMTYPE and into the implementation of the initializer StringSet::ini, and also into the main program FinalVT.

FactoryForceOverride:

Look into the property sheets and the implementations of the factory functions Framework::Application::CreateDoc and MyFramework::Application::CreateDoc, and also into the main program FactoryOverrideDemo.

 

See also our CallbackSample