3.3 Semantics of Virtual Classes
3.3.2 Inheritance with Virtual Classes
3.3.2.1 Explicit and Implicit Inheritance
Virtual classes can be related by explicit inheritance relationships with other virtual classes, e.g.,CascadeMenuItemon line 16 of Fig. 3.1 is declared as a subclass ofMenuItem. In addition, a virtual class implicitly inherits from its furtherbound, i.e. the virtual classes with the same name from the parent family, if one exists. For example,CascadeMenuItem
declared in MenusAccel (line 21 of Fig. 3.2) implicitly inherits from theCascadeMenuItem
of BasicMenus.
The explicit inheritance relationships between virtual classes are preserved, e.g.,
CascadeMenuItem in MenusAccel still inherits from MenuItem, even if this inheritance re- lationship is not redeclared on line 21 of Fig. 3.2. The inheritance relationships between virtual classes are, however, updated to refer to the newest version of the class. This means thatCascadeMenuItem in MenusAccel inherits from the new version ofMenuItem in
MenusAccel, declared on line 2 of Fig. 3.2.
Inheritance relationships are also updated in the inherited virtual classes that are not explicitly redeclared in the heir family. For example, MenusAccel does not redeclare
CheckMenuItemandRadioMenuItem, but these classes are automatically updated to inherit from the furtherbinding of MenuItem. Analogously PopupMenuand MenuBar are updated to inherit from the furtherbinding of Menu. As a result, even the classes not explicitly redefined in an heir family are not necessarily identical to their counterparts in the parent family.
In the case of virtual classes, the desired semantics of multiple inheritance, resulting from combination of implicit and explicit inheritance, can be clearly derived from the intended intuitive semantics. As was discussed in Sec. 3.2.1, the contents of the heir family class are seen as a description of change to the parent family. According to such view, the changes to a parent of a virtual classAcan never replace functionality defined directly for Ain the parent family – the furtherbinding of the parent of A only replaces the old version of the parent.
Such replacement of parents corresponds to the semantics of the mixins. In
a virtual class inheriting both from its furtherbound A and an explicit parent
B, the furtherbound is considered as a mixin combined with the parent class, i.e., A[B]. For example, MenusAccel.CheckMenuItem can be seen as inheriting from
BasicMenus.CheckMenuItem[MenusAccel.MenuItem]. In this case, BasicMenus.CheckMenuItem
Mixins(G) = G
Mixins(P.C) = [ Defs(P.C0) | C0 ← Ancestors(P.C) ]
Ancestors(P.C) = C Linearize([ Ancestors(P.C0) | C0← Parents(P.C) ]) Parents(P.C) = Linearize([ C | P0← Defs(P.C),
ClassDef (P0.C) = cclass C extends C1& . . . &Cn { . . . } ])
Defs(P.C) = [ P0.C | P0← Mixins(P ), ClassDef (P0.C) 6= ⊥ ]
Figure 3.10: Linearization of the inheritance graph of a given class C
3.3.2.2 Linearization of Inheritance Graph for Virtual Classes
As was discussed above, the semantics of inheritance relationships between virtual classes can be defined in terms of mixins. Thus, we can reuse the mixin composition semantics defined in Sec. 3.3.1 for definition of semantics of virtual classes. The computation of mixin list defined in Fig. 3.7 needs to be updated to incorporate the specific relationships of virtual classes. First, the mixin list must include the furtherbounds of a virtual class in addition to its (explicit) parents. Second, the algorithm must take to account that the parents of a virtual class can be inherited from its furtherbounds.
Linearization algorithm for virtual classes is given in Fig. 3.10. In the new definitions a class is identified not by simple name C, but by a path of class names separated by dots (P =G.C1.C2. . . .Cn), which specifies the location of the class in the nested structure of
classes, starting with a special class nameGrepresenting the global scope, e.g.,G.C1.C2
is a virtual class with name C2 in a family class with name C1. The class table ClassDef
now takes a path as a parameter.
The form of paths implies recursive class nesting structure, i.e., it allows virtual classes to act as family classes containing deeper virtual classes. The algorithm treats all virtual classes in a uniform way independently from their depth of nesting. The global scopeG
is introduced for convenience of treating top-level classes as if they were virtual classes ofG. The imaginary classGdoes not have any inheritance relationships, thus the mixin list of G contains only G.
The process of collecting the inherited mixins is distributed over multiple functions: Defs, Parents, Ancestors and Mixins. Defs(P.C) collects visible definitions of the class C in the context of P . In principle it is the definition of C in P itself and in its furtherbounds. Parents(P.C) collects the names of the declared parents of C from all its definitions in P . Ancestors(P.C) traverses the inheritance graphs defined by Parents
in order to collect the names of all ancestors of C in P , including C itself. Finally, Mixins collects all definitions of all ancestors of C in the context of P .
Each of the functions defines a different aspect of linearization of the inheritance links of a virtual class. According to the definition of Mixins(P.C) the furtherbounds of each ancestor of C are kept together in its mixin list. In particular, it means that the furtherbounds of C override the mixins inherited its explicit parents, which corresponds to the intuitive semantics of virtual classes as was explained above.
The internal order of each furtherbound group is determined by the mixin linearization of the enclosing class P as can be seen from the definition of Defs. It also determines the order of collecting the parents of a virtual class from its furtherbounds in Parents. The graph of ancestors of the class, based on the collected parents, is then sorted using the original linearization algorithm presented in Sec. 3.3.1, i.e., the function Linearize as it is defined in Fig. 3.7.
Note that such linearization corresponds to the intuition of considering an heir family as a description of difference from its parent, and its mixin list as the order in which these differences are applied. Indeed, the result of the mixin composition defined by the linearization of a virtual class C1.C2 defined in Fig. 3.10 is equivalent to first merging
the ancestor families of C1 in the order determined by the algorithm of Fig. 3.7, and
then in the resulting family class merging the ancestors of C2 again by the algorithm of
Fig. 3.7.
The presented linearization algorithm for virtual classes is different from the algorithm used in the formalization of virtual classes in [EOC06] and early implementations of CaesarJ [AGMO06], which are slightly simpler and do not support the described intu- ition, e.g., it is not guaranteed that the furtherbounds of a virtual class appear before the mixins inherited from its explicit parents in the linearization of the class.