The "Basics" of Inheritance
Microsoft has recently announced that the next version of Visual Basic will support inheritance. Visual FoxPro has had inheritance for the past 5 years, since Version 3.0, and Visual C++ has always had it. This article will take a closer look at what inheritance is and what it will mean for Visual Basic 7.
Inheritance is the mechanism typically regarded as the defining factor in whether or not a language is truly object-oriented. Developers who use languages such as Visual C++ and Visual FoxPro have often regarded Visual Basic as inferior, since it currently lacks inheritance - making it only object-based and not truly object-oriented. In reality, there are a number of defining factors that determine if a language is truly object-oriented. However, inheritance is certainly one of the most important. Visual Basic 7 will have inheritance, and it will be an extremely powerful addition to the language. In this article, we will use Visual FoxPro to demonstrate the basics of inheritance, its power, and what it will mean to Visual Basic developers.
To fully understand inheritance, we must first look at the concept of the class. Most developers have used a class in one way or another, potentially without even realizing or understanding that they have done so. For example, if you create a form and drop a button on it, you have actually created an object of a certain type, and that type is "button." The class is simply the specification of an object, including its behavior and attributes. In this example, the "button" class determines that the button is a gray rectangular object with text on it, and that it can be clicked. In Visual Basic and Visual FoxPro terms, this would be a collection of properties and methods. All object-based languages provide a default set of classes that may be used by the developer. These are typically referred to as "objects" or "controls." Also, note that classes are not necessarily visible. An object oriented language can create such objects for use and reuse, in addition to the set of predefined classes. Additionally, object-oriented languages must be able to subclass these classes for specialized usage.
This brings us to the main topic of this article - inheritance. When you subclass a class, you use the principles of inheritance. For example, imagine that there is a Visual Basic button that has become a "standard" within your program. Every time you use your button, you set several properties that represent the standards for your program. For example, you might change the font, the font size, the height and width of the button, and its color. Wouldn't it be nice if you could create your own standard button that already had all these properties set, but otherwise looked and behaved exactly the same as the standard Visual Basic button? This scenario is very well-known to Visual FoxPro programmers, since Visual FoxPro fully supports this capability through inheritance.
Let's have a look at how this can be done. At the time this article was written Microsoft has not yet announced the exact syntax for Visual Basic, so we will look at an example in Visual FoxPro. Visual Basic programmers who have not previously worked with Visual FoxPro will see that the Visual FoxPro code has many similarities and is easy to understand.
Here is the code that defines our "standard" button:
|DEFINE CLASS MyButton AS CommandButton|
Note that in Visual FoxPro, it would be easier to program this visually. However, to make the example easier to understand, we are instead showing the source code (see sidebar "Visual Classes" for more information).
This code is relatively straightforward. The DEFINE CLASS/ENDDEF tells Visual FoxPro that the code between the two statements defines our class. MyButton is the name of the class, and AS COMMANDBUTTON means that we want to base our new class on the existing Visual FoxPro command button. Our new command button will look and behave exactly the same as a standard Visual FoxPro command button, with the exception of the five properties (FONT, FONTSIZE, FORECOLOR, WIDTH and HEIGHT) that we have specified. We can now use this class on any Visual FoxPro form. Since we have defined our new class in source code, we can use it only from source code. However had we actually programmed this in Visual FoxPro's visual environment, we could then drag our new button out of the Visual FoxPro toolbox and drop it onto a form just as if it were one of Visual FoxPro's standard controls.
Now, imagine that you've created a large number of forms that all use your "standard" button. You present it to your customer and he likes its functionality, but prefers blue text instead of red. Without inheritance, you would need to open each form that contains this button and change the forecolor property. With inheritance, however, all you need to do is modify the color in the single class where the "standard" color is defined. Now, in any place where you have used this button, it will automatically have blue text instead of red.
So, in our example, to change the font color we would just change one line of code in our "standard" class:
But wait - it gets even better! What if, in a future version of Visual FoxPro, Microsoft changes the standard command buttons to have a "flat look"? Since we inherit from the base Visual FoxPro button, our special button will automatically inherit the new look and feel. The same is true in all common Visual Basic applications, but due to the dynamic nature of Visual Foxpro's inheritance, we not only inherit the new flat look, but all of our specialized settings are still maintained. Additionally, if we didn't like the flat look, we could change the look back to 3D in our command button class. Again, only one class would have to be modified.
Let's take this example one step further. There are many kinds of buttons that are used throughout applications in a similar fashion. Imagine a "Close" button, for instance. A close button is really just a specialized form of our command button. The only things special about it are its caption and the fact that it closes the form when it is clicked. Here is some code that defines our special close button:
|DEFINE CLASS CloseButton AS MyButton|
This button is subclassed from the button we created previously, which in turn was subclassed from Visual FoxPro's base command button. So this new class CloseButton inherits everything from those two classes. It is a FoxPro button, uses a red font (and the other 4 settings we changed), and in addition, the caption is set to "Close" and the click event actually closes the form. So, all we have to do now is drop this button on any form that needs a close button.
This is called multilevel inheritance. You can subclass as many levels as you want, creating more and more specialized classes.
Also, take note of the flexibility of this special command button. If, for example, you decide that you want to store the window position every time a form is closed, you simply add that code to the class we just created, and that functionality will be gained wherever the close button is used.
It is easy to think of other scenarios using the example classes we have so far. For instance, you may wish to create special close buttons, such as a "Save and Close" button. Here is some code for this:
|DEFINE CLASS SaveCloseButton AS CloseButton|
This class raises some very important questions. As we know, it inherits from the regular close button that defines a caption and closes the form when clicked. Our latest class inherits from CloseButton, so it will have all the functionality of that class, plus the special settings we define within this new SaveCloseButton class. One of them is the caption, which is now set to "Save & Close." This overrides the caption from the parent class. The other thing that's special in our new class is the click event. In the SaveCloseButton click method, we specified that we want to call the form's Save method when the button is clicked. The question is: What happens to the code in the parent class CloseButton.Click()? Will the form still be closed when the new button is clicked, or will it only save?
This depends totally on how the language implements inheritance. In Visual FoxPro, code from the parent class is automatically overridden when new code is added. So, the example above would not close the form. To close the form in addition to the save operation, we would need to change our SaveCloseButton.Click() method to the following:
This example saves the form before the default behavior is executed (inherited). Alternatively, I could execute the inherited behavior before the save operation, but this would not be a good idea in this example, since the form would already be released at that point.
Not all languages automatically override inherited behavior like Visual FoxPro. In those cases, all of the default code automatically executes before the specialized code. This is a somewhat safer approach, because it's easy to forget the DoDefault(), leading to skipped functionality and hard-to-find bugs. However, automatic inheritance also means less flexibility. In the example above, we needed to call the Save() method before the inherited code. With automatic inheritance, this wouldn't have worked, and we would have had to specify explicitly that we wanted to override the method, then add a reference to the parent class code after the save - the equivalent of DoDefault().
Microsoft has not made any announcements yet regarding the exact way that Visual Basic will handle inherited code, so we will have to wait to see exactly how it will work.
By now, we have a nice class hierarchy spanning 3 classes. As mentioned above, this is called "multilevel inheritance." This is not to be confused with "multiple inheritance," which is a mechanism that allows one class to inherit from more than one parent class. Code for multiple inheritance would look something like this:
|DEFINE CLASS xxx AS yyy AND AS zzz|
This is a very powerful mechanism, but is also very hard to manage and maintain. Although Visual C++ supports multiple inheritance, many modern languages, such as Visual FoxPro, do not. Although not formally announced, we have not heard any statements from Microsoft suggesting that Visual Basic 7 will support multiple inheritance.
A closer look at methods...
So far, we have defined only one method for our classes ? the click event. Now, let's take a closer look at some other aspects of methods. An object's methods can be defined as visible to the "outside world," meaning that they are part of the object's interface, and other objects can call these methods. Visual Basic and Visual FoxPro developers know these methods as "public methods." The opposite are methods that are visible only to the object itself. Such methods are very useful for performing small tasks that are part of a larger operation. They help keep each method small, yet don't clutter the interface. In Visual FoxPro, they are known as "protected methods"; in Visual Basic, they are "private methods."
There is also a third type of method. This method behaves mostly like a protected/private method, with the exception that it will not be visible in subclasses. Imagine that you have created a class that uses passwords, and one of the algorithms is used to decode and verify that the correct password has been entered. First of all, you wouldn't want any external object to access this method, since that would render the password protection useless. The method must be protected/private. However, you also wouldn't want a subclass of your object to override this method with code that accepted any password as the right one. So, the method also needs to be hidden from the subclasses. Visual FoxPro refers to these methods as "hidden" methods. We assume that Visual Basic will provide similar functionality.
The button example we have used so far has demonstrated the principles of inheritance, but it hasn't told the entire story. Inheritance is much more efficient on a large scale than it is for small objects like buttons. Just imagine business objects or behavior objects. A good example would be a business object that is used to calculate taxes. If you created an international application, taxes would have to be calculated for different countries and states, and possibly would even be dependent on the customer's location. A good way to solve this problem is through the use of a "Strategy Pattern" (Patterns are a widely used concept in object oriented programming. Patterns represent standard solutions to standard problems.). In a strategy pattern, different objects are invoked, depending on what country the taxes are calculated for. Of course, all these objects must contain the same methods and properties, so the user of that object doesn't have to worry about the details. This could be a major challenge.
In COM-based environments, the IMPLEMENTS feature is used to ensure object compatibility. Unfortunately, this mechanism is very inflexible, because once an interface is defined, it usually cannot be changed or enhanced. However, with inheritance, all of the methods can be defined in a common parent class, making all of the subclasses automatically compatible. Better yet, common behavior can be coded in the parent class, reducing the total amount of source code, but allowing special adjustments to be made in subclasses. The result: A highly flexible system design.
This is obviously just one small example out of many. In future issues of CoDe Magazine, we will discuss large-scale scenarios that use inheritance, and we will continue to discuss patterns on an ongoing basis.
Markus Egger and Ellen Whitney