Programming Guide:xppguide

Differences between Class(y) and Xbase++ Foundation

Class(y) is the leading third-party product for object-oriented programming under Clipper. The Xbase++ syntax for the object model is similar to Class(y), but does not copy the syntax because the object model and the implementations are different. The most important difference is that the Xbase++ compiler takes care of class declarations instead of the Clipper preprocessor, as used by Class(y). Because of how the preprocessor is used by Class(y), only one class can be declared in each PRG file. Xbase++ allows any number of classes to be declared in a single file. Class(y) translates each METHOD to a STATIC FUNCTION and the CREATE CLASS declaration to a FUNCTION. Xbase++ handles things differently. The compiler creates a class function from the CLASS declaration and creates references to method implementations, not STATIC FUNCTIONs. In Xbase++, a method differs from a static function because the variable self implicitly references the object executing the method. The variable self cannot be declared or changed within methods. Assigning a value to self or passing self to a function using the reference operator generates an Xbase++ compiler error.

An important instance variable in Class(y) is ::super. This instance variable does not exist in Xbase++ since it is not appropriate for clearly identifying superclass objects in multiple inheritance scenarios. Xbase++ accesses the member variables and methods of each superclass using the name of the superclass. Example:

CLASS DataDialog FROM XbpDialog 
   METHOD init 

METHOD DataDialog:init( parameters ) 
   ::xbpDialog:init( parameters ) 
RETURN self 

The :init() method of the superclass must be called by this explicit "cast" in Xbase++. Any visible method in any superclass can be explicitly called by specifying the class name in the call to the method.

Another important difference between Class(y) and Xbase++ is the fact that class methods and class variables are only accessible through the class object under Class(y). Under Xbase++, each instance of a class has access to class methods and class variables. Calling a class method can occur via any object (instance) of a class in Xbase++. Class variables are also accessible through instances. Xbase++ does not require a MESSAGE...TO CLASS to be declared in the class to delegate class variable and method calls to the class object.

Since the Xbase++ syntax for declaring classes and methods is so similar to the Class(y) syntax, porting Class(y) code to Xbase++ is relatively easy with help from the preprocessor. As an example, the preprocessor directives included below translate Class(y) code to Xbase++:

/*  Class(y)                                Xbase++  */ 
#ifdef __XPP__ 

#command CREATE CLASS <x> [FROM <y>]  => CLASS <x> [FROM <y>] 
#command MESSAGE <x> METHOD <y>       => METHOD <x> IS <y> 
#command CLASS MESSAGE <x> METHOD <y> => CLASS METHOD <x> IS <y> 
                                         // Name of the superclass 
#xtrans :super                        => :<superClassName> 

#include "Class(y).ch" 

If Class(y) code is to be ported to Xbase++, the preprocessor can be used to accommodate differences in syntax. The #ifdef directive allows the same code to be compiled using either Clipper/Class(y) or Xbase++. The PRG file containing the Class(y) class declaration just needs to be compiled using preprocessor directives that translate the existing code into valid Xbase++ code.


If you see anything in the documentation that is not correct, does not match your experience with the particular feature or requires further clarification, please use this form to report a documentation issue.