3.2 Instance programming and pseudo-subclassing

Instance programming and pseudo-subclassing

Visual FoxPro has features called instance programming and pseudo-subclassing. You may not have heard about them since they aren't widely discussed or generally known; however, almost everybody uses them without even knowing it.

This feature must be easy to use, but every now and then, the lack of specific knowledge brings up some serious problems. For this reason, I'd like to discuss this issue in detail, which should help you to use all the power of pseudo-subclassing and instance programming without running into their potential problems.

Instance programming

What exactly is instance programming? Well, let me give you a little example. Let's assume we create a form class that contains one command button. We add some code to the command button to release the form when the button is clicked. Figure 1 illustrates this scenario.

Figure 1. Our form class and command button.

To review: We created a new form class (let's call it IP for instance programming), which is a subclass of the FoxPro base class Form. The IP class has a member object called cmdCancel, which is a command button. This button is a subclass of well let's have a look at the Properties window in Figure 2.

Figure 2. The Properties window.

Hmmm the Properties window says it doesn't have a parent class. That's strange. After all, I told you we couldn't create a class that didn't have a parent class. So what is the actual class? See Figure 3.

Figure 3. The current class of the Properties window.

FoxPro says the current class is CommandButton. That's strange, too! We just created a class that doesn't have a parent class, and the current class name is a FoxPro base class. Did we create such a class?

In fact, we didn't! All we created was a subclass of the FoxPro form class that had a predefined instance of a command button. There was no subclassing going on with the button. It is just an instance of the CommandButton FoxPro base class. So theoretically, we shouldn't be able to add code to one of the button's methods. Rather, we should create a button class, add the code there, and drop the button on the form. Everything else would break all kinds of object rules, because we would add code to an object rather than to a class.

However, adding code directly to object instances allows us to develop prototypes and actual applications at tremendous speed; it's one of FoxPro's most important Rapid Application Development (RAD) features.

By the way, creating FoxPro forms is 100 percent instance programming because not even the form itself is subclassed.

Pseudo-subclassing

Now let's take this a step further and create a subclass of the whole IP form class. This class (let's call it PS for pseudo-subclassing) inherits everything from the IP class, including properties, methods, and all predefined member objects plus their assigned properties and methods.

Take note that only the form has been subclassed, just as in the IP class. The button is still of class CommandButton and doesn't have a parent class (well, it has, but only an internal one). However, FoxPro is very generous and will still allow you to add code to the button. In fact, you can even overwrite and inherit code just as if it were a real subclass. This is called pseudo-subclassing.

Most people use the terms pseudo-subclassing and instance programming interchangeably. However, they are not the same thing. Internally, pseudo-subclassing and instance programming are handled very differently. As you'll see later (when I explain how visual classes are stored internally), visual classes are stored in FoxPro tables. Each class gets one record in this table, as do all the newly defined member objects. FoxPro stores the code that is added to an instance (instance programming) in each member's record. When applying pseudo subclasses, the new class inherits all the information about the members but does not create a record for each of them, so FoxPro doesn't have a good place to store the new code and the overwritten properties. So it uses a little trick and stores this data directly with the class record. To assign the code and properties to the member objects, FoxPro adds the name of each object. So the button's Click method is now called "Function cmdCancel.Click" rather than "Function Click" as it would be in normal scenarios.

Of course, the user never sees these things, but he might experience some resulting problems. Let's try to fool FoxPro a little. To do so, we go back to the IP class and rename the Cancel button cmdCancelButton. Now let's look at the button in the PS class. The button is still there and it inherited the new name from its parent class. However, for some strange reason, all the code we assigned to this button has been removed. On first sight, this might appear to be a bug, but if you think about it, it's rather simple. As we've just discussed, FoxPro stores the name of the member object in order to assign the code to it. The code that has been removed belonged to an object called cmdClick. Of course, this object can't be found anymore because we renamed it. The subclass cannot know that the button in the form is still the same object. It thinks we removed the original object and added a new one. If we want to recover the original code, we need to cancel the current operation, go back to the parent class, and rename the button to its original name. Make sure you don't save the subclass. Otherwise FoxPro simply removes all your code and you'll have to start over from scratch.

This behavior might seem bad, but it used to be worse. In earlier versions, FoxPro thought the class library was corrupt whenever it couldn't find referenced objects, and wouldn't allow us to modify it at all. Imagine if you renamed an object in a class at the beginning of a class hierarchy. You might have to start your whole project from scratch again. Considering these facts, the current situation appears quite acceptable. After all, the advantages outweigh the disadvantages by far, especially when you're aware of the possible problems.

But wait, there's more! If you use DoDefault() in the member object's method, you can move on to the next paragraph, but if you use the scope resolution operator (::), you are in deep trouble. The scope resolution operator requires the name of the parent class, the method name, and possibly some parameters. But as we already know, the command button doesn't have a parent class, so we can't provide the necessary information for the scope resolution operator. This is one of the reasons why DoDefault() was introduced in Visual FoxPro 5.0. However, there are some tricks to make this work, even if you use Visual FoxPro 3.0, which didn't have DoDefault(). Here's an example that uses the previous example to demonstrate how this would work:

IP.cmdCancel::Click()

This code would go in the Click() event of the button. Remember I told you FoxPro simply stores the methods with the class and adds the name to assign the code to each object? We can now use this fact to our advantage and add the object name in front of the message name. This way, FoxPro can identify the code we try to run and execute it, even if the syntax doesn't seem to match the normal scope resolution requirements.

However, I recommend using DoDefault() instead, even though you might take a bit of a performance hit. I think the ease of maintenance outweighs that by far. Keep in mind that neither instance programming nor pseudo-subclassing is truly object-oriented. They are shortcuts to make the developer's life easier and more productive. If you want to avoid all the troubles this might introduce, you could go the truly object-oriented route. You could create a form class, create a button class, and finally create a subclass of the form class and change nothing but drop the button on it. Whenever you wanted to change the behavior of the button, you would create a subclass of the button and another subclass of the original form, and drop the button on this form as well. This becomes a nightmare if you have many member objects. Imagine a form that has only five members. Depending on how you want to change the behavior, you could end up with as many as 25 different subclasses of the form. Now imagine you have 25 different objects rather than five. In this case, you might end up with 625 different subclasses. This, of course, would be the case only when you wanted to change the behavior of each object independently from all the other objects, which is improbable.

I think you can see the issue, and I believe it's well worth it to accept the disadvantages of instance programming and pseudo-subclassing instead.



Advanced Object Oriented Programming with Visual FoxPro 6. 0
Advanced Object Oriented Programming with Visual FoxPro 6.0
ISBN: 0965509389
EAN: 2147483647
Year: 1998
Pages: 113
Authors: Markus Egger

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net