Peter Wone - GUI Computing
Both Java and Delphi are single-inheritance based programming environments.
This is great until you want to inherit properties and methods from two (or more) ancestor classes.
Then what? Cut and paste the code? Bad karma. A major purpose of inheritance is to avoid doing this. Cut and paste denormalises your code. You have to apply any bug fixes or enhancements in more than one place if you do that.
Visual Basic uses a containment model (in C++ Microsoft calls it aggregation) in which, if you want class B to 'inherit' the properties or methods of class A, then class B must create internally an instance of A.
Suppose class A has a method A.Method and you want class B to 'inherit' this method. What you would do in Visual Basic is create a method B.Method - the code for which calls A.Method. Properties of class A can be similarly wrappered.
This approach is much clumsier than true inheritance, which is one of the main drawbacks of Visual Basic. But you can apply aggregation in Delphi or Java (or C++, for that matter) in cases where you can't use true inheritance, because you already used it to inherit from another parent.
The best strategy is to inherit directly from the most complex immediate ancestor, and inherit via containment from all the other ancestors.
One advantage of aggregation over true inheritance is that you can suppress properties and methods – i.e. choose not to inherit them.
The most significant aspects of emulating multiple inheritance in Delphi or Java are:
In the Visual Basic environment, implementing inheritance via containment has to be done every time you want to inherit. You end up with boatloads of code that has nothing to do with the program specifically, and pertains instead to infrastructure management - thus the programmer gets plenty of extra opportunities to mess up.
Delphi and Java, on the other hand, do all this automatically behind the scenes. The kludge can still be applied, and it can be hidden behind a wall of protected functions. There is one implication for descendants. The business of destroying the contained object(s) can be handled in the Destructor method of the class which enjoys multiple inheritance. Descendants which override their destructor methods must call the (Delphi syntax) "inherited Destroy;" destructor as the last thing they do to ensure that the ancestor's contained objects are properly destroyed.
In a nutshell, in Visual Basic we have containment damage, whereas in Delphi and Java we have damage containment.
While this article contains all the relevant information to implement the technique, you may glean more insight from a working example. I refer you to this issues zipped sample code for my article 'Generating HTML Links from Folder Contents'. In that code, TFolderContentsLinkTable inherits directly from TObject and inherits via containment from TFolderContentsLinksList.
Now that you know how to deal with the issue of multiple inheritance in Delphi, investigate the sample code.
There is no reason that HTML tables should only contain lists of folder contents. Create a class THtmlTableFromStringList which solves the general problem of tabulating a list, and then apply your new knowledge to re-implementing TFolderContentsLinksTable - by inheriting from TFolderContentsLinksList and THtmlTableFromStringList.
Hint: the only properties you need from TFolderContentsLinksList are RelativeURL and Strings.