Fundamentals of Object-Oriented Programming


Menachem Bazian

Flash Creative Management, Inc.

Introduction

Microsoft® Visual FoxPro™ presents us with a radically new way of looking at building applications. With the addition of object orientation to the product, Microsoft FoxPro® has matured into a development language that allows us to build arsenals of classes to speed us along the road to building bullet-proof applications quicker than we ever thought possible.

The watchword in FoxPro 2.x development was reusability. Still, FoxPro 2.x’s modular style of development did not enforce this practice. Frequently, modules built in FoxPro 2.x were first built “specific” and only later made generic.

The core of software development in an object oriented environment is creating base classes and then building additional classes and objects from those classes. This, by definition, forces us to think in terms of reusability.

Visual FoxPro is a “hybrid” language. Like C++, FoxPro does not require that you use object-oriented programming (OOP) in your systems. Software may still be developed modularly as it was done in the past. OOP, however, adds a powerful new dimension to our software development efforts.

This session will introduce Object Orientation and show examples using Visual FoxPro 3.0.

An Introduction to Object Orientation

OOP is not really a new method of programming. It really is a new way of looking at programming. When you get into it, you will find that these new concepts are really based in things we already know. All it takes is an understanding of what all the terminology and ten-dollar words mean, how these concepts can affect your system design and how they add tremendous power to the development language.

Objects

The base unit we will be working with is called an object. In real terms, an object can be anything. For example, a computer is an object. So is a house, a car, a telephone, a candle, you name it.

Sometimes an object is a collection of other objects. For example, a computer may be an object, but it is made up of a keyboard, processor, disk drives, etc.— each of which is an independent object as well.

The common denominator of all objects is that they know everything they need to know to do what they do. For example, a car has everything it needs to do what it has to do. For example, the steering mechanism accepts information from the driver and the car knows how to interpret the drivers actions into the movement of the car. The shocks adjust to the input of the road, the engine drives the wheels, etc.

Objects used in software development are more abstract than the examples presented here. For example, we can define an object called customer in which we define what the object contains and does. Another object used in OOP would be an object used in a form (called a control). Typical examples of these objects would be push buttons, radio buttons, text boxes (GET fields), and more.

We’ll look at the customer and push button objects some more as we go through each topic in our discussion of OOP.

Characteristics of an Object--Its Properties

Look at your average candle. How would you describe it? You might say that it is three inches long, red in color, tapered, with a cotton wick at the top. Each of these descriptive characteristics is what is known in OOP terminology as a property (also known as an instance variable) of the object. Each object has properties that describe it.

To move back to programming concepts, for a minute, take a look at the old FoxPro 2.6 push button. What might the properties of that be? Well, for a few, the caption (e.g., OK, CANCEL), width and height of the button, location on the screen (a.k.a. form), etc., are all properties of the push button.

That’s all there is to properties.

Going back to our customer example, where we define what the object is, we could have many properties for a customer. For example, the customer’s name, address, telephone number, credit limit, etc., would all be properties of a customer.

The beauty of the OOP model is that properties become directly referenceable as part of the object. Let’s take the example of changing the prompt (i.e., the Caption) of a push button. In FoxPro 2.6, we would modify the button attached to the variable, lhOk, with the following command:

SHOW GET m.lhOk,1 PROMPT "It's OK"

In an OOP programming environment, you access the property directly as part of the object. For example, here’s a common syntax for this:

lhOk.Caption = "It's OK"

Notice the use of the dot operator. The idea behind this bit of code says that there is an object on the screen called lhOk that has a property called Caption (which controls what the user sees as the prompt for that object). This line of code sets the caption property to “It’s OK,” which will then automatically update the display of the object on the form.

Here’s another one. Disabling an object is also likely done is a similar manner. In the old way, an object on a screen is disabled with:

SHOW GET lhOk DISABLE

as opposed to the OOP way that would be something like:

lhOk.ENABLED = .F.

which would automatically disable the object. You could also hide an object with:

lhOk.VISIBLE = .F.

Note the change in approach to modifying the characteristics of an object. In the old way, we did it indirectly using commands that work on the screen. Now, we are working directly on the object itself.

Changing the properties of a customer object work the same way. For example, to set the name of a customer, we could modify the customer’s NAME property as follows:

Customer.Name = "Flash Creative Management, Inc."

Actions Associated with Objects--Methods

A premier concept in OOP programming is called encapsulation. This means is that an object has attached to it everything it needs to handle itself. We have already seen, for example, that the characteristics of an object are bound to it as properties. In addition to properties, an object can also have actions attached to it to perform specific functions. For example, if you had a light switch, you would need to have some way of toggling the light on and off when the user flips the switch. To put it in more “computerish” terms, if you had an invoice object, the procedure to print that invoice would be bound to the invoice object.

These actions which are attached to objects are known as methods.

The key here, now, is that we can attach code to any object. Going back to the light switch example, we could have a method called Toggle that turns (toggles) the light on and off. Something like this (written in pseudo-code, of course).

Procedure Toggle
IF light_is_on
	Turn_Light_Off
ELSE
	Turn_Light_On
ENDIF
ENDPROC

If we were to assume that we had a light switch in the kitchen (we’ll call the name of the object Kitchen_Light), we could fire the method to toggle the light on and off by issuing:

Kitchen_Light.Toggle

In our customer object, we could have a method to move from one record to the next when in a form. We could call this method, Nextit, in the following manner:

Customer.Nextit

This is a very powerful way of working with code. By having a method called Nextit, which moves on to the next record, you can make your code more generic. For example, you could have a “Next” button on a toolbar that always calls a method called Nextit. The object currently being worked on (e.g., a Customer, an Invoice) could be passed through as a parameter. Thus, by executing a single line of code like:

toObject.Nextit

where toObject is the name of the parameter variable accepting the object, you could always execute the method appropriate for the current table.

Let’s take the next step and look at events.

Events

Events are just that—things that happen automatically. For example, clicking the mouse is an event. When using objects on a Microsoft Windows® form (like a push button), you can attach code (i.e., methods) to these events. When the event happens (i.e., the user clicks the mouse on the object), the associated method is automatically called.

Events are nothing new. We have been using them the since the advent of FoxPro 2.0. Valid clauses, for example, are simply procedures which are attached to an event (attempting to exit a modified field or clicking on a push button). The power of using objects comes in attaching procedures to an object which automatically fire when something specific happens. In Visual FoxPro, for example, you can attach methods to all kinds of events: when the mouse is clicked down, when the mouse is released, etc.

There is one major difference between events in an object oriented development environment and the old valid and when clauses. In FoxPro 2.6 there was no direct method of manually firing the code snippet attached to an event (there is a way, but it is a kludge). In other words, there is no single command that says Run the procedure attached to a screen object’s Valid event. In an object oriented development environment, you can do this easily by calling the event as you would a method. For example, if you had a push button called cmdOK, you could fire the Click event (which happens automatically when the user clicks the mouse on the push button) at any time by issuing:

cmdOk.Click
By attaching code to the Windows events we greatly increase the control we have over the behavior of a form.

So far, we have seen that we can create objects, assign properties to them and create methods for them. If we have to write code to fine tune an object every time we create it, we would be in for a lot of coding. Fortunately, OOP has the answer for this as well—CLASSES.

Understanding Classes

Earlier in this article, I discussed a candle as an object. The candle had certain properties such as its color, length, width, etc. However, how is a candle created?

A candle is created by pouring molten wax into a mold (with a wick inside, of course). When the wax cools, you open the mold and out pops the candle. Using a mold, you can create many candles all with the same characteristics.

A class is, in effect, a mold. All objects are created from classes. When a class is defined, you specify what the properties are (color, height, width, position, etc.) and what the methods are. Objects are then created by instantiating them (a fancy word for pouring the wax into the mold and waiting for it to cool) from the class.

Let’s take a quick look at how we can define a class. For the purposes of this example, I will return to the light switch example:

DEFINE CLASS light AS custom
  status = "OFF"
  
  PROCEDURE LightSwitch
   IF this.status = "OFF"
     this.status = "ON"
   ELSE
     this.status = "OFF"
   ENDIF
  ENDPROC
ENDDEFINE

This piece of code creates a class called LIGHT. Light has one property, called Status, which is initialized to OFF. The PROCEDURE code is a method which is attached to the class.

In effect, what we have just done, is defined what a “light” object will have and do.

We instantiate, or create, the object from the class using a command or function which says, basically, “create an object with the characteristics of the class and give it a name.”

x = CREATEOBJECT("light")

This code, for example, will create an object based on the class called “light” and give the object a name called X. Once we have run this code, we can access all the properties of the object as described before. For example...

? x.Status 		&&Returns "OFF"
x.LightSwitch	&&Run method "lightswitch" 
					&&defined in the class
? x.Status 		&&After running lightswitch, 
					&&this would return "ON"

Basing a Class on Another Class--Subclassing

So far we have discussed just about all there is to know about objects. We have discussed what objects, properties, methods and events are. We have also discussed how we create an object’s blueprint with a class which we then use to instantiate the object. One more important piece remains—the real exciting part as it turns out. Creating classes based on prior classes.

In our LIGHT class, we created an object that basically had one property and one method. This works real well for all the light switches in the world that just turn the light on and off. Suppose I want to create a light switch that dims as well? What do I do? Do I have to write a whole new class? The toggle is still applicable; you can still turn the light on and off. All I need is a modified version of the LIGHT class that has all the capabilities of the LIGHT class and one additional capability: dimming the light.

For the purposes of this illustration, I’ll set the following rules. When you attempt to use the dimmer, it will go from full light to half light and then back again. In order to turn the light off or on, you still need to use the original lightswitch method.

Here’s how we could accomplish this using an OOP model.

DEFINE CLASS dimmer AS light
  intensity = "FULL"

  PROCEDURE DimmIt
   IF this.status = "OFF"
     RETURN
   ENDIF
   
   this.intensity = IIF(this.intensity = "FULL", ;
              "HALF", "FULL")
   WAIT WINDOW "Lights are now "+this.intensity+" power."
  ENDPROC
ENDDEFINE

Note the original DEFINE of the class. In the original define (class LIGHT), we used CUSTOM as the base class. CUSTOM basically means that there is no base class, we are creating one from scratch. In the DEFINE we use here, the base class is LIGHT. This means that DIMMER automatically gets everything that LIGHT has. Thus, although no code exists in the DIMMER class to handle the LIGHTSWITCH method and the status property, DIMMER gets it automatically by virtue of it being a subclass of LIGHT.

In effect, a subclass (e.g., DIMMER) is a more specialized version of the “super class” (e.g., LIGHT).

This is known as Inheritance.

Understanding Polymorphism

The final point to be made here is Polymorphism. All this means is the ability to call methods with the same name and have it mean different things based on the object you are working on.

For example, let’s take our Light objects. All have a method called Toggle which turns the light on and off. Support, now, that I were to create an entirely different object: a telephone. The telephone object may or may not have anything to do with a light object but there is a method attached to it which is also called Toggle which does something.

Now, let’s take a look at this bit of code:

oLight = CREATEOBJECT("Light")
oPhone = CREATEOBJECT("Telephone")
oLight.Toggle	&&Runs the Toggle method from 
				&&the Light object
oPhone.Toggle	&&Runs the Toggle method from 
				&&the Phone object

Encapsulation Revisited

Taking the concepts that we have seen here, encapsulation becomes clearer. Basically, encapsulation means that an object is a self contained unit. It contains data, in the form of properties (also called instance variables), and methods associated with it to perform whatever actions the object needs to do what it needs to do.

We saw this with the Light class of objects.

We can also create a Customer class if we wanted to and associate data and methods with it that encapsulate customer information and actions within.

A customer object’s data would be such items as Name, Address, Phone Number, Credit Limit, etc. Methods associated with the object could be actions related to displaying customer data, allowing the user to edit/add customers, printing a customer, etc. If you develop naming conventions for your object methods, using the objects become a breeze. The following example will use two mythical classes, customer and invoice. Note how the code, at this level, can be exceedingly similar. In fact, using OOP, the developer who takes objects and puts them together in the form of a system, will have a much easier job.

oCust = CREATEOBJECT("Customer")
oCust.Display	&& Show the customer
oCust.Edit		&& Edit the Customer
oCust.Save		&& Save Customer
oCust.Print		&& Print the customer

oInv = CREATEOBJECT("Invoice")
oInv.Display		&& Show the Invoice
oInv.Edit		&& Edit the Invoice
oInv.Save		&& Save Invoice
oInv.Print		&& Print the Invoice

Messages, Messages, Messages

If you read any literature on OOP, the concept of “messages” is littered throughout. When working on OOP based systems, everything we have just discussed is described as “sending a message.” If we look at the examples of working with objects listed above, we can define them as follows:

Creating an Object

oInv = CREATEOBJECT("Invoice")

This line of code sends a message to the Invoice class telling it to create an object based on itself called oInv.

Getting the Value of a Property

lnAmount = oInv.nAmount

This can be described as sending a message to the oInv object telling it to get the value of the nAmount property and to return it to lnAmount.

Calling a Method

oInv.Display && Show the Invoice

Calling a method can be termed as sending a message to the oInv object to execute its method called Display.

If we understand the concept of a message, a great deal of the gobbledygook we read in OOP literature becomes understandable. For example, Polymorphism has been defined as “The ability to send the same message to different objects and have different actions take place.” Translated into English, this means that I can have the same method name in multiple objects that do different things.

The moral of this story is: don’t let the language throw you.

OOP and its Effect on Development

So, now that we have seen what objects are and what all the ten dollar words mean, the next question is, “Big deal. What does this do for me?”

OOP will shift the focus of development from coding procedures to the designing and defining classes. Since Objects are, in effect, complete and independent “modules” it is possible to have developers just working on classes of objects. The application developers can then use these classes, either directly or by subclassing them, and put them together to form a system.

Does this mean that once you have a library of classes that you will never need to write code again? Not quite, but it will make your life a lot easier once you have the class library developed, debugged and ready to go.

System Maintenance with OOP

Users like to change things, right? Suppose, using our light example, the user changed the base definition of a light switch. In our example, a light switch only has one property (called status) and one method (called Lightswitch). Suppose the company redefined the base light switch (class LIGHT) to have an additional feature. Now, when the user turns the light off or on, the system will tell them what they have done.

In order to accomplish this, all we need to do is modify the Class definition of the light as follows:

DEFINE CLASS light AS custom
  status = "OFF"
  
  PROCEDURE LightSwitch
   IF this.status = "OFF"
     this.status = "ON"
   ELSE
     this.status = "OFF"
   ENDIF
  WAIT WINDOW "Light is now " + this.status
  RETURN
ENDDEFINE

From this point on, all object instantiated from the class LIGHT will get the changed method. In effect, we have changed the behavior of every object based on this class by adding one line of code to the class definition.

But wait, there’s more. Not only have we modified all the objects based on class LIGHT, we have also modified every object based on subclasses of light (e.g. Dimmer). This makes for a powerful way of developing reusable code. The flip side to this is if you break a class, you may also break all the subclasses (regardless of which application you have used it in) based on it. If you have used the class in a production application, you’ll need to be very careful with this.

The Visual Class Designer--Introduction

Along with the new object-oriented programming (OOP) language extensions, Visual FoxPro 3.0 also includes a visual Class Designer development tool for creating and managing class libraries. This session includes a detailed explanation and demonstration of the Class Designer and how it interacts with other related Visual FoxPro tools. Rather than re-writing the Class Designer chapter of the Visual FoxPro manual, these session notes are designed to give architectural information about the Class Designer and how it relates to other Visual FoxPro tools such as the Form Designer and the Class Browser. Refer to the Visual FoxPro 3.0 manuals on the Class Designer for a detailed descriptions and illustrations as a supplement to these notes.

Objects vs. Functions

Many developers new to object-orientation often question the difference between objects and user-defined functions (UDF). First, let’s discuss the concept of abstraction.

Abstraction involves concepts such as information hiding and black-box segments. The idea is to create reusable software components in which users of these components do not have to have knowledge of their internals in order to use them. In structured design, abstraction is implemented with functions. In object-oriented design, abstraction is implemented with objects.

The primary difference between functions and objects is that functions (UDFs) are basically behaviors or logical code routines. Objects, on the other hand, are a collection of functions known as methods and data known as properties or attributes. Objects are self-contained entities at runtime based on a blue-print design known as a class. Objects take information hiding one step farther by introducing the next step beyond abstraction, which is known as encapsulation. Encapsulation involves embedding methods (functions) and properties (variables) together while hiding any details of the objects’ internals. Each object is given its own responsibilities.

Another way to think of an object is the concept of abstract data types, which is simply a high level structure that relates to real world objects better than standard language data types.

Object-orientation introduces another significant concept known as inheritance. A useful analogy for inheritance involves defining genetic cells, or DNA. Think of how organisms reproduce and contain both behaviors and attributes from the organisms of which they were derived. Usually there are many similarities, but always some differences. You could think of the original DNA structure like an original blueprint. Then think of the offspring as a modified blueprint based on the original. Realize that an entirely new blueprint was not created from scratch, but rather referenced from the original with certain changes or differences.

In object-oriented terms, software DNA are known as classes. Classes are simply definitions at design time from which objects are created, or instantiated, at runtime. Classes define both behavior (methods) and attributes (data) which are basically templates that generally map real world concepts down to a software level. New class blueprints can be created from scratch (these are known as base classes), or can be derived from existing classes (known as subclassing). When subclasses are created, the original class is then referred to as the superclass of the subclass, and the entire process is known as inheritance.

Based on these concepts, class hierarchies can be constructed for related classes, allowing maximum reusability. Groups of related class hierarchies can be bundled together to create class libraries. Once class hierarchies are created at design time, then objects can be instantiated at runtime.

Once objects are active in memory, program execution basically consists of objects sending messages to other objects. A Draw message might be sent to a box object to draw itself, a Print message might be sent to an invoice object to print itself, and a Print message might be sent to a document object to print itself. Creating common method names such as Print, Draw, Refresh, etc. that are independent of the object type is known as polymorphism.

Polymorphism allows a common sequence of messages to be sent between objects. If classes defining the objects are modified or redefined, the sequence and content of messages don’t necessarily change. The details of a box, invoice, or document could all be modified or completely redefined at the class level while the actual program execution would remain unchanged. In a pure object-oriented system, the only procedural code consists of objects being created, objects sending and receiving messages, and objects being destroyed. So the question you might be asking is, “how do these new concepts and new terminology relate to my current coding practices?”

If you write well-thought-out modular procedural code that is focused on reusability, then you’ve got a significant head start on OOP. Many FoxPro developers have traditionally jumped right into coding when starting an application. Without having the problem completely defined and thought out, individual pieces of the application are written and then eventually glued together towards the end of the development cycle. Also, the pieces usually rely on each other in order to function properly. There might be situations when you have to make a change to a piece of an application that results in having to change other areas of the source code since they are dependent on each other. One example would be having to change the standard background color for all forms in the application since each form would have to be modified. A more significant example would be having to add a new attribute to all employee related data, like the addition of an employee e-mail address. This would not only affect the data tables, but also any logical code that interacts with the data. GUI forms and reports that display or edit the employee information would all need to be modified individually. Some of the many benefits of object-oriented programming are that application modifications like these become easier, require less effort, and are less likely to result in negative effects on other components in the system.

Visual Classes vs. Coded Classes

VCXs vs. PRGs

Choosing between implementing classes using the Class Designer (VCXs) or through standard code files (PRGs), it is simply a design decision. Using the Class Designer to implement classes offers many more benefits than creating classes in PRG files. With the Class Designer, you can create subclasses using the Class Designer or create instances on forms using the Form Designer. Along with being able to use visual tools for increased productivity, visual class libraries (VCXs) hierarchies can be viewed in various ways using the Class Browser.

Class Hierarchies

When you design a class hierarchy, you are defining a structure which by definition should remain intact. If you make a change to a particular class, the change should be reflected in any of its subclass or any composite class using that class as one of its properties. If a change you are about to make to a class may have a negative effect on existing related classes, that is probably a sign that you need to create a new subclass rather than change the existing one. Classes should relate in an abstract way, meaning you should not have to know how they work internally in order to use or interface to them.

Class Implementation

In a typical business application, you have screen objects like an entry for the phone number or an OK or Cancel button. Most applications contain more than one form with one of these same objects. Beyond that, many apps use the exact same controls as other apps. So essentially you’re duplicating work over and over. Now suppose you want to make a change to the standard, like the phone number format mask or validation, or even the color of a button or entry textbox.

If you make a change to your single class definition, changes will propagate throughout every form, application, etc. which use that class. You could change the standard color of a particular control and you wouldn’t even have to open any of the existing forms in order to inherit the change. Just run the form or program and the new properties and methods take effect.

ADD OBJECT vs. CREATEOBJECT()

There is a very important difference between ADD OBJECT at the class template and CREATEOBJECT() for a member declared as a property at the class template level. The rule is that when you use ADD OBJECT in a class definition, the object becomes a member of the container and can use the Parent property to refer to the immediate container object.

When using CREATEOBJECT on an instance variable of an object, that property is simply being used as a reference to the instance of the newly created object, but is not a member of the container and therefore cannot use the “parent” property since the object is not part of the container.

Class Designer vs. Form Designer

Classes vs. Code Generation

With Visual FoxPro 3.0, when you find yourself saying, “I could do it in 2.6 by modifying GENSCRN or using GENSCRNX,” this should be an indication for you to start thinking about a class hierarchy to solve the problem using object-orientation. There is no reason for code generation with Visual FoxPro since it is now an object-oriented language. You can build classes and class relationships that allow you the same flexibility as FoxPro 2.x code generation (SPR) but with the power of encapsulation, polymorphism, and inheritance.

Returning a Value from a Modal Form

The following is an example wrapper class used to allow forms to return values. It uses a simple naming convention that the return value memvar must be called luRetValue. Since dialog forms which return values are normally modal, the example assumes that the form called is modal.

*-- The DoForm class is the wrapper class and 
*--  the DoForm UDF is used to call it.
*-- Simply set memvar luRetValue in any code 
*--  snippet within a form/control method.
*-- The exit code for the form should be 
*--  RELEASE thisform *and* CLEAR EVENTS.
*-- This example set would need to be enhanced 
*--  to support parameter passing to the form.

? DoForm("MyForm.SCX")	&& Form MyForm.SCX should set
										&& luRetValue for the 
										&& return value.
RETURN

FUNCTION DoForm(tcFileName)
LOCAL oDoForm
oDoForm=CREATEOBJECT('DoForm',tcFileName)
RETURN oDoForm.Show()

DEFINE CLASS DoForm AS Custom

	cFileName=''

	FUNCTION Init(tcFileName)
	this.cFileName=tcFileName
	RETURN .T.
	ENDFUNC

	FUNCTION Show
	PRIVATE luRetValue
	luRetValue=.T.
	DO FORM (this.cFileName)
	READ EVENTS
	RETURN luRetValue
	ENDFUNC

ENDDEFINE

VCX vs. SCX

Components of an application are developed in the Class Designer (VCX) by creating classes visually while applications are assembled in the Form Designer (SCX). Not every line of method code and every property setting needs to be saved as a class when building an application. So adding code and setting properties to objects in an SCX makes sense if specialized changes are not intended to be reused. The SaveAsClass function makes it easy to create classes in a VCX from objects in an SCX.

The Class Designer allows developers to create classes visually. These classes can be either visual or non-visual (Custom) subclasses. Custom properties and methods can be added to a class which appear in the Properties window for visual editing. The Form Designer allows forms to be created by subclassing existing classes by dropping them onto the form surface from the Controls toolbar or from the Project Manager.

The object model in Visual FoxPro supports container classes. Container classes are classes that can contain objects as members. The Form and Formset in an SCX is a container. The Formset can contain Form objects while the Form can contain control and Custom objects. The Toolbar class is a container that can contain control objects. Control classes such as the CommandButton class is not a container class since it cannot contain objects.

If you experiment with the Save As Class... menu option when in the Form Designer, you’ll notice you can save controls as classes into a visual class library (VCX). You can also select multiple controls and save all selected controls. You can even save an entire form (including its object members) as a single class. When you select an individual control (or just the form) and you save the selected (single) object as a class, you are creating a class based on the object’s classification. When you save a group of selected controls or the entire form which contains controls into a single class, you are actually saving a container class.

Adding Properties and Methods to Classes

Visual FoxPro’s object model does not allow you to add properties or methods to objects within a container class. Now how does this relate to the form designer and the fact that methods and properties can be added to the form, but not any of the controls? The answer is in the above description when you realize that when you create a form (SCX) using the form designer, you’re actually creating a single Form (or Formset) container class.

Since Visual FoxPro does not allow object members of a container class to add methods and properties visually, the Add Property... and Add Method... dialogs in the Form Designer and Class Designer only apply to the form (or Formset) and not any of the added object member controls and custom objects. The Form Designer is actually creates a single container class (either Form or Formset), just like a container class built using the Class Designer, the same rules apply. Only the highest level parent can have added custom properties and methods. When in the Form Designer, you are not defining classes, you are actually manipulating live object instances in a design mode.

Containers vs. Non-containers

For ease of use, Visual FoxPro allows you to define child object properties (using the WITH clause of ADD OBJECT) and object code (ex. FUNCTION Command1.Click) within a container class. However, you shouldn’t do it if you plan to reuse the added object. The following example demonstrates the reusability problem:

DEFINE CLASS MyForm AS Form

	Caption="My Form"
	ADD OBJECT cmdButton AS CommandButton WITH ;
		Caption="Not reusable"

	FUNCTION cmdButton.Click
	WAIT WINDOW ;
		"Not reusable in other classes or subclasses"
	RETURN
	ENDFUNC

ENDDEFINE

Now if you want to build another form, you can’t reuse the implicit CommandButton subclass embedded within my MyForm class. If you were to generate code from a Visual FoxPro SCX which was built using the Form Designer, the code would also look like this. Essentially, the Form Designer is a tool to implement a single form or formset container class. The key is to avoid this technique if you plan to reuse the child objects. For example, you can’t reuse a CommandButton which sits on a form (SCX) in the Form Designer. You must first save it as a class or define it as an independent class. The proper object-oriented way to do the above example is as follows:

DEFINE CLASS MyForm AS Form

	Caption="My Form"
	ADD OBJECT cmdButton AS MyCommandButton

ENDDEFINE

DEFINE CLASS MyCommandButton AS CommandButton

	Caption="Reusable"

	FUNCTION Click
	WAIT WINDOW ;
		"Reusable in other classes or subclasses"
	RETURN
	ENDFUNC

ENDDEFINE

Now you can use the MyCommandButton class in other classes or subclass it.

Custom Builders for Visual Class Libraries

Builders in Visual FoxPro are programs that interact with a form or any of its controls while in the Form Designer or Class Designer. Builders allow direct manipulation of properties and methods while in design mode. The general difference between Wizards and Builders is that Wizards are designed to quickly step you from point A to point B for a particular process while Builders are used to edit methods and properties of live objects in the Form/Class design mode.

Builders are re-entrant, which means they interact with existing properties and methods of an object or objects and often act like a user-friendly object editor. Visual FoxPro 3.0 ships with many built-in builders for classes on the Standard control toolbar (Textbox, Editbox, Grid, Combobox, Listbox, etc.) along with special Builders such as the Form Builder and the AutoFormat Builder. The built-in Visual FoxPro Builders are packed in an application called BUILDER.APP.

When using _BUILDER=“<path>BUILDER.APP,” BUILDER.APP will check the selected object for a custom property called Builder. If a custom property called Builder of type “character” exists and contains a valid .PRG, .FXP, .APP, or .SCX file name, then the builder specified by the Builder property will be executed. The purpose of the reserved Builder property is for declaring a specific builder within a class definition using the Visual Class Designer (VCX). This will allow custom Builders to be distributed along with class libraries. Simply keep the associated Builders in the same directory as the class libraries (VCXs) to allow a specific Builder to be executed. Creating a custom Builder property can be useful with custom class libraries (VCXs) when subclassing in the Class Designer or adding object instances in the Form Designer since the Builder can act as a high-level interface between the developer and any method and/or property members of the class.

Class Browser

The Class Browser in Visual FoxPro 3.0 is written in FoxPro and is specified by a system variable named _BROWSER which defaults to _BROWSER=SYS(2004)+”BROWSER.APP”. The Class Browser opens a single or multiple visual class libraries (VCXs) and is a modeless application. The Class Browser is launched by selecting Browser from the FoxPro system menu which executes the program defined in a system variable called _BROWSER. The Class Browser supports both visual and non-visual (Custom) classes. Multiple instances of the Class Browser may be launched. Selecting Browser from the FoxPro system menu always launches a new instance while the Window menu list is used to activate an existing instance.

Glossary

Abstract Data Type

A data type defined by the programmer that is not supported by the language. These data types are generally high level definitions within a program that correspond to real world objects.

Abstraction

The benefit of ignoring irrelevant details of software components and focusing on only those details required to interface, send messages, etc. Some of the concepts of abstraction include information hiding and black box routines. Since most real world objects include abstract details, objects allow an improved representation of real world objects as compared to functions.

Class

A blueprint, or template, for defining methods and properties of a particular type of object. Classes are defined at design time and are not executed at runtime. Objects are created based on class blue-prints at runtime. Multiple objects can be created (instantiated) from a single class at runtime.

Class Hierarchy

A tree structure of classes that represent the relationship between a set of classes of similar type. The top node of a class hierarchy is known as the base class while related classes below it are known as subclasses. Although any number of levels of subclasses can be created, most methodologies state that well-defined class hierarchies should not exceed about five levels deep.

Composite (Container) Object

An object that contains one or more objects. This occurs when at least one instance variable of an object is of type object. Composite objects, along with delegation, are typical techniques to eliminate the unwanted side effects of multiple inheritance (see inheritance below).

Delegation

Delegation occurs when an object receives a message and passes it on to another object. Delegation is useful when responsibilities of objects are passed on to other objects. Non-OOP languages can also support delegation simply by defining a UDF to simply pass any parameter(s) on to another UDF. The interface to the developer sending the message does not have to know about the internal details.

Encapsulation

The concept of methods (procedures or functions) and properties (data memory variables) packaged together. The result of this packaging is the object. Objects contain both methods and properties. The methods are referred to as the object’s behaviors and the properties are referred to as the object’s attributes.

Inheritance

When a class is derived based on another existing class, the existing methods and properties are referenced for reuse with the new class. A subclass uses all of the methods and properties defined in the superclasses above it within the class hierarchy. Inheritance can be broken for individual methods and properties when creating a subclass. This is known as specialization.

Generally the term “inheritance” implies single inheritance. In some languages such as Microsoft C++, multiple inheritance is supported. In multiple inheritance, a single subclass can be derived from more than one superclass. Along with the problems of naming conflicts within the union of methods and properties of the superclasses, multiple inheritances is usually considered an improper class hierarchy design solution. The combination of composite objects and delegation is superior to multiple inheritance.

Instance

A term which describes a runtime occurrence of an object belonging to a particular class. Classes are defined at design time, while object instances are created from defined classes at runtime.

Message

An instruction from one object (the sender) to another object (the receiver) to execute one of the receiver’s methods. The three parts of a message are defined by the receiver object name, the method name, and any parameters the method may require. Messages can also be two-way, which occurs when the receiver object’s method returns a value to the sender.

Object

A software collection of related methods (functions) and data (memory variables). Generally the methods act on the associated data. Generally an object refers to an instance of a class.

Polymorphism

The ability to send the same message to various objects while each object is responsible for acting on the common message. Polymorphism allows a common interface to be created for objects sending messages. For example, sending the message “Draw” to both a box object and a circle object would be an example of polymorphism since the message that was sent to each object had the same name while each object contained its own Draw method. A Draw method would be defined in both the Box class and the Circle class and each may have similar or completely different behaviors. Polymorphism is supported by allowing the same method name to be defined within different classes.