While the DataFlex class-construction process does not support multiple inheritance, it does support a method of importing common methods into a class. The Mixin class provides some of the functionality of multiple inheritance without its overhead or complexity. This advanced technique should primarily be of interest to tool builders. All of the DataFlex data-entry classes make extensive use of this technique.
Often multiple classes will all need to exhibit similar behaviors. If these classes share the same superclass, these common behaviors will all be acquired through inheritance. For example, all of the data-entry classes acquire their user-interface behaviors through class inheritance. In other cases, common behaviors cannot be acquired through inheritance. In a single-inheritance object system, this means that these non-inherited behaviors must be added to each class. An example of this is the data-server-connectivity behaviors that all DEOs must exhibit. While you could accomplish this by including the same code in every class, this duplication has a high overhead.
Rather than requiring you to include duplicate code, DataFlex supports the ability to import all functions and procedures from one class into another. This is similar to including the actual functions and procedures in each class without the overhead of duplication. Because the imported class does not import the class structure itself, this is not multiple inheritance. This should be thought of as a method of importing skills into classes.
The command import_class_protocol provides the mechanism for importing skills (functions, procedures, and properties) from one class into another. This command supports several options that are documented in full in the Language Reference.
Classes from which skills are imported are special-purpose classes, often with names ending with _mixin. Not only can these classes not be subclassed, they cannot be instantiated,either. Objects needing the skills of the "mixin" class are based on a (non-mixin) class that imports the skills. Mixins should be based on the Mixin class. This is a simple class based on cObject. It contains no new methods, events or properties. A mixin class has no native methods because those methods should never be mixed into another class. Only the interfaces actually defined in the mixin will be mixed into another class.
We have two classes that both need to share a number of common procedures that will not be acquired through class inheritance. We will place all of these procedures in a mixin class. These skills will all be imported with the import_class_protocol command. Here is the package that contains the mixin class, called new_skills_mixin:
// NewSkill.pkg Use VdfBase.pkg Class New_Skills_Mixin is a Mixin Procedure New_Skill_1 : End_Procedure : Procedure New_Skill_37 : End_Procedure End_Class
This package contains the first of the two importing classes:
// Deo1.pkg Use DeoSpr1.pkg // the superclass deo class package Use NewSkill.pkg // our mixin class package Class Deo_1 is a Some_Deo_Super_Class : Import_Class_Protocol New_Skills_Mixin : End_Class
This package contains the second of the two importing classes:
// Deo2.pkg Use DeoSpr2.pkg // the super class deo class package Use NewSkill.pkg // our mixin class package Class Deo_s is a Some_Other_Deo_Super_Class : Import_Class_Protocol New_Skills_Mixin : End_Class
The above method shows how to import procedures and functions. Properties also may be imported. Since properties should be created during the construct_object process, we will need to send a message in construct_object (in the importing class-mixin classes should never contain a construct_object procedure). The procedure to handle this message will reside in the mixin class. We will define our properties inside of this procedure.
The following example shows how to mix in properties. Here is code from the mixin package:
// NewSkill.pkg Use VdfBase.pkg Class New_Skills_Mixin is a Mixin // this will get called once and only once during the // construct_object phase of the main class. Here we can // declare properties, set properties or set accelerator keys. Procedure Define_New_Skills_Mixin Property Integer piProp1 0 : Property Integer psPropX "XXX" End_Procedure Procedure New_Skill_1 : End_Procedure : Procedure New_Skill_37 : End_Procedure End_Class
Here is an importing-class package:
// Deo1.pkg Use DeoSpr1.pkg // the deo superclass package Use NewSkill.pkg // our mixin class package Class Deo_1 is a Some_Deo_Super_Class Procedure Construct_Object Forward Send Construct_Object : send Define_New_Skills_Mixin // define any properties or whatever. End_Procedure : Import_Class_Protocol New_Skills_Mixin : End_Class
You can import mixin classes at any class level, you can import as many mixin classes as you wish, your mixin can contain as many messages as you wish, and your importing class may contain any number of messages. If a mixin class and the importing class both define or augment the same message, one of the augmentations will be ignored. If two mixin classes define or augment the same message, one of the augmentations will be ignored. The last message handler defined will actually be the message. This kind of overlap is usually undesirable, and when it occurs it is usually a bug. Because of this, you must be careful with the management of your mixin classes.
The use of mixin classes is an advanced technique and is certainly not required for successful programming. It is however, a very powerful technique. If you wish to learn more about this technique, you are encouraged to review the DataFlex package files in the /pkg folder.