ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿ ³ DB/C Newsletter ³ ³ January 1994 ³ ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ Editor's Notes I've been talking about the Internet in this space for the past few months. Well, we've decided to take the plunge. We expect to have a 56kbps leased line connection to the Internet in place by the end of January. Our plan is to move all DB/C support to the Internet and to shut down the dial-in DB/C BBS sometime in 1994. The DB/C Newsletter will continue to be published on a monthly basis. It will be available to via two methods: downloading and e-mail. You will be able to download the current newsletter, along with all back issues, by using ftp. You will also be able to get the newsletter by subscribing to an e-mail service. If you are subscribed, we will e-mail you the newsletter when it becomes available. The DB/C BBS public file areas that contain source code and other information will be available by ftp. All other support activities will be handled via e-mail. If you don't have direct access to the Internet and you don't currently subscribe to something like Compuserve in the USA, you should probably look into it. I know Compuserve has e-mail links to the Internet, but does not yet support ftp. DELPHI, a service like Compuserve, supports full access to the Internet. There are many regional BBSs that also provide Internet access. We will be glad to help you figure out how to get access when the time comes for us to shut down the existing DB/C BBS. We'll give you complete information about our Internet connection in the next newsletter. If you would like to help us test it out and currently have ftp and e-mail access to the Internet, leave a message or give us a call. The International DATABUS User's Group has scheduled the next conference for April 24-26, 1994 in Houston, Texas. We will be participating and hope to see you there. If you would like information, contact Andrea Rye at voice: (713) 784-1762 or at FAX: (713) 784-0790. During the last few months, we have communicated with several DB/C programmers about Object Oriented Programming Languages (OOPL) and DB/C. There is a great deal of interest in adding object oriented features to DB/C. This month's article gives a detailed plan for turning DB/C into a real OOPL. PLEASE NOTE: these are plans only and are not a commitment to actually implement any or all of these features into a future release of DB/C. Please let us know if you think the plans have merit. Any feedback you can give will be appreciated. Thanks in advance. DNW Object Oriented DB/C Before we discuss the details of OO DB/C, let's review the fundamentals of object oriented programming languages. In his 1988 book "Object-oriented Software Construction", Bertrand Meyer specified 7 levels of object-oriented features that define how object-oriented a programming language is. These levels are: 1. Object-oriented modular structure 2. Data abstraction 3. Automatic memory management 4. Classes 5. Inheritance 6. Polymorphism and dynamic binding 7. Multiple and repeated inheritance There has been some refinement of these concepts over the last few years, but they are generally accepted as the definition of what is an OOPL. Here is a syntactic summary of the features we plan to add to DB/C. I will explain how they work in the text that follows the syntax definitions. ------------------- START OF SYNTAX OF OO FEATURES IN DB/C ------------------- [ ] means optional lower case are elements/symbol names upper case are literal keywords/characters other symbols are literal characters classname CLASS DEFINITION [ PARENT=classname ] [, MAKE=routinelabel ] [, DESTROY=routinelabel ] CLASSEND Inherited variable definitions are normal variable definitions whose operand field starts with a &. Inherited variables may only be defined and used inside a CLASS DEFINITION/CLASSEND pair. Inherited variables need not contain variable length/format information or correct array size specification. All other information must be specified. All variables declared inside the CLASS DEFINITION/CLASSEND pair are inheritable, except those inside ROUTINE/ ENDROUTINE pairs. classname CLASS [ MODULE=charlit ] methodname METHOD objectname OBJECT verbname VERB !classname [, parmspec] methodname [ parmlist ] methodname [ parmlist ] MAKE objectname prep classname CALL methodname [ WITH parmlist ] DESTROY objectname The form of methodname execution that contains is required for user verbs without the !classname operand in their definition. The existing form of the VERB statement (without !classname) is used for calling methods explicitly. -------------------- END OF SYNTAX OF OO FEATURES IN DB/C -------------------- Here is a small example of how to define and use a class. This example is contained in a single source file. . main program PERSON CLASS SHOWPERSON METHOD PERSON1 OBJECT DISPLAY *ES, "Create and destroy person demonstration" MAKE PERSON1 FROM PERSON CALL SHOWPERSON DESTROY PERSON1 STOP . definition of person class PERSON CLASS DEFINITION, MAKE=NEWPERSON NAME CHAR 30 BIRTHDATE CHAR 6 NEWPERSON ROUTINE KEYIN "Enter name: ", NAME: *N, "Enter date of birth: ", BIRTHDATE RETURN ENDROUTINE SHOWPERSON ROUTINE DISPLAY "Name: ", NAME: "Date of birth: ", BIRTHDATE RETURN ENDROUTINE CLASSEND The only new data type is OBJECT. This is an actual data type, just like FORM, DIM, INT, FILE, etc. In the example, PERSON1 is the name of the variable that will contain an object of the class PERSON. Note, that an object variable can contain an object of any class. The PERSON1 object is created by the MAKE statement. When we say created, we mean that a set of data variables of the class is created and its reference is stored in the OBJECT. This is very similar to the existing DB/C concept of creating an instance of a loadmod. In our example, the two variables, NAME and BIRTHDATE, are created and the reference to their data area is stored in PERSON1. The DESTROY verb removes the object (i.e. the data variables) and makes any references to them (such as the reference in PERSON1) invalid. When the object is created, a special routine is called to help create the object. In our example, this routine is called NEWPERSON. It is special because it is specified as the MAKE method on the CLASS DEFINITION statement. Note the term "method". This is the object-oriented term for a routine that is contained in a class. In our example, the PERSON class has two methods, NEWPERSON and SHOWPERSON. Note that in our main program, we only had to declare the SHOWPERSON method because it is the only method explicitly used. The NEWPERSON method is called implicitly by the MAKE statement. The MAKE and DESTROY methods are optional for a class. In our example, we don't have a DESTROY method. The call to the SHOWPERSON method is very similar to a regular call statement except that the object being referenced is contained in < >. Note that there could be more than one class containing a SHOWPERSON method. At run-time, the class of the object referred to by PERSON1 is used to determine which SHOWPERSON method is called. This feature is called polymorphism. In addition to the call statement, we can use the DB/C user verb syntax to call a method. In our example, after the SHOWPERSON METHOD statement in the main program, add the following line: SHOWPERSON VERB and change the call statement to: SHOWPERSON The operands on a user verb work the same way whether it is calling a method or a regular routine. We can separate the class definition from the program that uses a class. In our example, let's assume the main program will be in a source file called "main.txt" and the person class source code will be in the file "class1.txt". The only change required is to change the CLASS statement in the main program like this: PERSON CLASS MODULE="class1" The MODULE parameter defines the name of the .dbc file that contains the code defining the PERSON class. Note the default extension is .dbc, just like for CHAIN and LOADMOD. The file "class1.dbc" is not a library, it is just a normal .dbc file created by DBCMP. Multiple classes can be defined in a single source file. Classes cannot be nested. Inheritance is the most important object-oriented feature. As an example, let's assume we want to create a new class called EMPLOYEE that inherits all of the features of PERSON, and adds some. The employee class definition will be in a source file named "employee.txt". Here is how we define it, assuming that the PERSON class is in a .dbc file named "class1.dbc": . definition of employee class PERSON CLASS MODULE="class1" SHOWPERSON METHOD EMPLOYEE CLASS DEFINITION MAKE=NEWEMPLOYEE, INHERIT=PERSON SALARY NUM 6.2 NEWEMPLOYEE ROUTINE KEYIN "Enter salary: ", SALARY RETURN ENDROUTINE SHOWEMPLOYEE ROUTINE CALL SHOWPERSON<> DISPLAY "Salary: ", SALARY RETURN ENDROUTINE CLASSEND The main program looks like this: . main program EMPLOYEE CLASS MODULE="employee" SHOWEMPLOYEE METHOD EMPLOYEE1 OBJECT DISPLAY *ES, "Create and destroy employee demonstration" MAKE EMPLOYEE1 FROM EMPLOYEE CALL SHOWEMPLOYEE DESTROY EMPLOYEE1 STOP Notice that the main program doesn't even know of the existence of a PERSON class. When the MAKE statement executes, an EMPLOYEE object is created. The INHERIT operand of the EMPLOYEE class definition statement specifies that a PERSON object is also to be created and its variables are "merged" with the variables defined in the EMPLOYEE class. After the variables are created, the PERSON class MAKE method is called, after which the EMPLOYEE class MAKE method is called. In the SHOWEMPLOYEE method, there is a call to the SHOWPERSON method that does not specify an object (nothing is contained in the <>). This syntax means the current object. In other programming languages, it is known as "this" or "self". Please note that calls to routines that are not defined as methods and that are contained in the same class definition are normal - they do not require <>. Methods are inherited. In our example, we can access the SHOWPERSON method from the main program by declaring it as a method and calling it. As far as we know, it is in the EMPLOYEE class, but it is actually in a class that is an ancestor of EMPLOYEE. Variables can also be inherited. Inherited variables have the & character as the first character of the operand field on their declaration. In addition, because they are fully defined in the ancestor class, size information is not needed. Size information is the field size and the number of entries in each dimension of an array. Other type information is required. Please note that inheriting variables from an ancestor is optional. You only need to declare those variables in the new class that you need to access directly. Here is an example using the EMPLOYEE class: . definition of employee class PERSON CLASS MODULE="class1" EMPLOYEE CLASS DEFINITION MAKE=NEWEMPLOYEE, INHERIT=PERSON SALARY NUM 6.2 NAME CHAR & BIRTHDATE CHAR & NEWEMPLOYEE ROUTINE KEYIN "Enter salary: ", SALARY RETURN ENDROUTINE SHOWEMPLOYEE ROUTINE DISPLAY "Name: ", NAME: "Date of birth: ", BIRTHDATE: "Salary: ", SALARY RETURN ENDROUTINE CLASSEND Here are some examples of inherited variable declarations: In the ancestor, the actual declarations are: NUMVAR NUM 5.2 . numeric variable ARRAY1 CHAR 5[10,10] . array of 100 character variables PTRARRAY NUM @[25] . array of 25 pointers to numeric variables ARRAYPTR NUM []@ . pointer to one dimensional array ARRAYPTR2 NUM [,]@ . pointer to two dimensional array FILE IFILE KEYLEN=20, FIX=200 . index file variable In the inheriting class, the declarations are: NUMVAR NUM & ARRAY1 CHAR &[,] PTRARRAY NUM &@[] ARRAYPTR NUM &[]@ ARRAYPTR2 NUM &[,]@ FILE IFILE & There is one other feature that we is not really object-oriented, but is quite useful. It is called the implicit object calling method. In the following example, the class definition code is contained in a source file named "message.txt" and the main program is in "main.txt": . this is the class definition code MESSAGE CLASS DEFINITION ERRORMSG ROUTINE TEXT TEXT CHAR @ DISPLAY *HD, "ERROR OCCURRED: ", TEXT: *W=5, *HD, *EL; RETURN ENDROUTINE CLASSEND . this is the main program MESSAGE CLASS MODULE="message" METHOD ERRORMSG VERB ERRORMSG !MESSAGE, #CVARLIT DISPLAY *ES, "Error message test program" ERRORMSG "UNABLE TO FIND FILE" STOP When "!class" is the first operand on a user verb definition, that user verb is considered to be an implicit object call user verb. When the ERRORMSG statement is executed, an unnamed object of class MESSAGE is created, its MAKE method is called (in this example, there is none), and the method whose name is the same is the user verb is called. When that method returns, the DESTROY method is called (in this example, there is none), the unnamed object is destroyed and the program execution returns to the calling program. This is quite convenient for execution of routines that do not need to have variables persist beyond their return. And that's it. We have met all of the requirements for being an object- oriented language, with the exception of automatic memory management. In fact, C++ and many other OO languages in use today don't meet that criteria either. In general, only SMALLTALK and derivatives of LISP do automatic memory management. All other aspects of an OOPL are implemented including classes, dynamic binding, multiple inheritance, and polymorphism. DB/C Class Schedule The next DB/C classes scheduled for January 31 through February 3. The classes are held in the Oak Brook, Illinois office of Subject, Wills & Company. For more information, contact Judi Tamkevic at (708) 572-0240.