Single and multiple inheritance of MDL classes is a key feature of MDL classes. Inheriting all protected local and interface parameters as well as the member functions of a number of parent MDL classes for defining a new MDL class can be achieved by extending the standard syntax for the definition of an MDL model (Section 3.2) by a list of parent classes:
NewModel MDL_Class_Name : Mdl_Parent_List {
MDL_Definition_Blocks
}
Mdl_Parent_List is a comma separated list of MDL classes which serve as parent classes.
The thereby defined new MDL class MDL_Class_Name inherits all protected local and interface parameters of each of its parent classes. Since the documentation and default values are adjectives of the particular parameter instances, the inheritance mechanism includes these attributes, too.
Analogously MDL_Class_Name inherits every MDL method of its parent models except for the evaluate, construct, and destruct methods.
The MDL inheritance mechanism differs significantly from the inheritance mechanism of C++. The parents of C++ classes allocate resources for all member variables and methods within the class layout of the child class, whether they are inherited in a public, protected or private manner. These resources are initialized by calling designated constructor methods in conjunction with the constructor of the child class. The philosophy of the MDL inheritance mechanism is to manage with a minimum of resources. Therefore the MDL inheritance mechanism is defined to allocate only resources for actually inherited parts of the parent classes. No resources are allocated for parent class elements with the protection type private. Thus the constructor methods of the parent classes become invalid and are not evaluated during the instantiation of the derived MDL class instance. The protection identifier not only specifies the access rights for derived classes as compared to C++ but actually influences the layout of inherited MDL classes.
In C++ name conflicts between elements of different inherited classes have to be resolved manually. Within MDL class definitions name conflicts are resolved by inheriting only the element stated in the last parent involved in the conflict.
When this inheritance behavior is not suitable, an inheritance scheme similar to the C++ scheme can be enforced by using protected parameters in the parent classes and simultaneously inheriting and aggregating the parent MDL classes. The automatic linkage mechanism of sub-Model parameters will ensure the correct initialization of inherited parameters by the constructors of the matching sub-Model.
Example 3.13 depicts how to use inheritance for defining an MDL class which will calculate the result of the function . SimpleFunc implements the concept of functions using the interface parameters :x and :y. The nominator and denominator functions are implemented as MDL classes by inheriting their interface from SimpleFunc. The final SiFunc model inherits the methods sinus and div from its two parent classes SinusFunc and DivFunc. The common interface of all these classes is defined by the base class SimpleFunc which is inherited directly by SinusFunc and DivFunc and indirectly by SiFunc via the interface definition of DivFunc due to the above mentioned conflict solving strategy for multiple inheritance.
NewModel SimpleFunc {
Interface {
protected Parameter<double> x;
protected Parameter<double> y;
}
}
NewModel SinusFunc : SimpleFunc {
sinus { :y = sin(:x); }
}
NewModel DivFunc : SimpleFunc {
div { :y /= :x; }
}
NewModel SiFunc : SinusFunc, DivFunc {
Local {
// double_eps for a 53 bit IEEE mantissa
Parameter<double> dbl_EPS = exp(-52*ln(2));
Parameter<double> eps = 2.*sqrt(6.*dbl_EPS);
}
evaluate {
if ( fabs(:x) > eps ) {
call sinus;
call div;
} else {
:y = 1.0;
}
}
}
Example 3.13: Multiple inheritance of MDL classes