Jump to content

Class Objects in SOM: Difference between revisions

From EDM2
Ak120 (talk | contribs)
Ak120 (talk | contribs)
mNo edit summary
 
(5 intermediate revisions by 2 users not shown)
Line 15: Line 15:


==Goals of SOM==
==Goals of SOM==
SOM is a language neutral mechanism for developing object-oriented class libraries. SOM consists of a run-time repository for class information and a series of language bindings. Pictorially we can describe SOM as shown in Figure 1.
SOM is a language neutral mechanism for developing object-oriented class libraries. SOM consists of a run-time repository for class information and a series of language bindings. Pictorially we can describe SOM as shown in Figure 1.


''Figure 1. SOM Run-Time Class Repository and Language Bindings''
''Figure 1. SOM Run-Time Class Repository and Language Bindings''
Line 398: Line 398:
Given a new class for class objects, we can have any number of classes associated with the new class object. For example, instead of <tt>StudentFactory</tt> we might have used the metaclass name <tt>CountFactory</tt> to indicate greater generality, and then used this metaclass whenever we want to keep track of total instantiated objects.
Given a new class for class objects, we can have any number of classes associated with the new class object. For example, instead of <tt>StudentFactory</tt> we might have used the metaclass name <tt>CountFactory</tt> to indicate greater generality, and then used this metaclass whenever we want to keep track of total instantiated objects.


Often we do not need such generality and we only intend for a given class object to be associated with one class. For example, the only change to the metaclass might be the addition of new constructor methods which are only applicable to a specific class. In such cases we can use a slight short cut to redefine the metaclass. This short cut is called implied metaclass. The main advantage of implied metaclasses is that the class definition file for the metaclass can be folded into the class definition file for the class it controls, and similarly for the class implementation file.
Often we do not need such generality and we only intend for a given class object to be associated with one class. For example, the only change to the metaclass might be the addition of new constructor methods which are only applicable to a specific class. In such cases we can use a slight short cut to redefine the metaclass. This short cut is called implied metaclass. The main advantage of implied metaclasses is that the class definition file for the metaclass can be folded into the class definition file for the class it controls, and similarly for the class implementation file.


The student implementation file rewritten to use the implied metaclass is shown in Figure 11. The student implementation file rewritten to use the implied metaclass is shown in Figure 12.
The student implementation file rewritten to use the implied metaclass is shown in Figure 11. The student implementation file rewritten to use the implied metaclass is shown in Figure 12.
Line 425: Line 425:
   int      countObjects(), class;                  <--
   int      countObjects(), class;                  <--
</pre>
</pre>
Notice there are two new keywords used to define implied metaclasses. The keyword "classprefix" indicates a prefix used to identify methods associated with the class object. The keyword "class" is used to identify data members or methods associated with
Notice there are two new keywords used to define implied metaclasses. The keyword "classprefix" indicates a prefix used to identify methods associated with the class object. The keyword "class" is used to identify data members or methods associated with the class object.
the class object.


''Figure 12. Student Class Implementation using implied Metaclass''
''Figure 12. Student Class Implementation using implied Metaclass''
Line 494: Line 493:


==Summary==
==Summary==
The class object is an important source of runtime information in SOM. Virtually anything that one might want to know about a class can be found out through one of the class object's methods. The class object is itself a fully functional object, like any other object in SOM. It has its own class, by default <tt>SOMClass</tt> which can be modified using any of the normal class modification techniques including inheritance and polymorphism.
The class object is an important source of runtime information in SOM. Virtually anything that one might want to know about a class can be found out through one of the class object's methods. The class object is itself a fully functional object, like any other object in SOM. It has its own class, by default <tt>SOMClass</tt> which can be modified using any of the normal class modification techniques including inheritance and polymorphism.


The class object is an important programmer resource. It is the source of runtime information about classes and gives the ability to make runtime decisions about how objects will be manipulated. Because the class object is a standard SOM object, instantiated from a standard SOM Class, you have considerable flexibility to redefine its characteristics as needed.
The class object is an important programmer resource. It is the source of runtime information about classes and gives the ability to make runtime decisions about how objects will be manipulated. Because the class object is a standard SOM object, instantiated from a standard SOM Class, you have considerable flexibility to redefine its characteristics as needed.


==References==
==References==
*Sessions, Roger: ''Class Construction in C and C++: Object-Oriented Programming Fundamentals'', Prentice Hall, Englewood Cliffs, New Jersey, 1992 (IBM Doc. S242-0086).
*Sessions, Roger: ''Class Construction in C and C++: Object-Oriented Programming Fundamentals'', Prentice Hall, Englewood Cliffs, New Jersey, 1992 (IBM Doc. S242-0086). [https://openlibrary.org/works/OL15964549W/Class_construction_in_C_and_C?edition=classconstructio00sess]
*Sessions, Roger and Nurcan Coskun: Object-Oriented Programming in OS/2 2.0, ''IBM Personal Systems Developer'' (Winter 1992): 107-120.
*Sessions, Roger and Nurcan Coskun: [[Object-Oriented Programming in OS/2 2.0 Using SOM]]. ''IBM Personal Systems Developer'' (Winter 1992): 107-120.
*''SOM: OS/2 2.0 Technical Library System Object Model Guide and Reference'', Prentice Hall, 1992 (IBM Doc. 10G6309)
*''SOM: OS/2 2.0 Technical Library System Object Model Guide and Reference'', Prentice Hall, 1992 (IBM Doc. 10G6309) [https://www.os2museum.com/files/docs/os220tl/os2-2.0-som-1991.pdf]


==ACKNOWLEDGEMENTS==
==Acknowledgements==
SOM is the work of many people. Mike Conner developed the initial idea and implementation, and continues to lead the overall design of SOM. Andy Martin designed the SOM Class Interface Language, and designed and implemented the class Interface compiler. Larry Raper implemented many features of the run time library and porteed SOM to OS/2. Larry Loucks provided close technical tracking and was instrumental in focusing the effort. Other SOM developers include
SOM is the work of many people. [[Michael H. Conner|Mike Conner]] developed the initial idea and implementation, and continues to lead the overall design of SOM. Andy Martin designed the SOM Class Interface Language, and designed and implemented the class Interface compiler. Larry Raper implemented many features of the run time library and porteed SOM to OS/2. Larry Loucks provided close technical tracking and was instrumental in focusing the effort. Other SOM developers include Nurcan Coskun, [[Scott H. Danforth|Scott Danforth]], Hari Madduri, Roger Sessions, [[Simon C. Nash|Simon Nash]], and John Wang. The project is managed by Gerry Ronga.
Nurcan Coskun, Scott Danforth, Hari Madduri, Roger Sessions, Simon Nash, and John Wang. The project is managed by Gerry Ronga.
 
[[Category:SOM Articles]]

Latest revision as of 01:10, 11 November 2022

by Nurcan Coskun and Roger Sessions

Note
  1. Words inside angle brackets should be computer font.
  2. Bold lines are indicated by "<--" in right margin.

Abstract

This article continues the discussion of SOM begun in the winter issue of the Personal Systems Developer. In this article we look at one of the advanced programming features of SOM: the class object. The class object can be used to retrieve at run time a great deal of useful information about classes, including the name of the class and the methods supported. The class object also knows how to instantiate objects of a given class. We give an overview of the class object, and discuss the concept of metaclass. A metaclass of a given class is the class of that class's class object. We show the two important techniques for changing a class's metaclass.

Introduction

In the winter issue of the Personal Systems Developer (Sessions and Coskun, 92), we gave an introduction to the System Object Model (SOM). SOM is a new methodology for creating object-oriented class libraries introduced by IBM in OS/2 2.0. In our last article we discussed the basic concepts of object-oriented programming: developing classes and instantiating objects; deriving new classes through inheritance; and resolving methods with polymorphism. We also discussed the primary goals of SOM: multi-language support (including both procedural and object-oriented languages); upwardly compatible binaries; and object-oriented extensions to nonobject-oriented languages.

In this article we are going to explore an advanced feature of SOM: the class object. We assume that you are familiar with the introductory concepts of our last article. If you find yourself getting lost here, you should go back and revisit our winter article.

Goals of SOM

SOM is a language neutral mechanism for developing object-oriented class libraries. SOM consists of a run-time repository for class information and a series of language bindings. Pictorially we can describe SOM as shown in Figure 1.

Figure 1. SOM Run-Time Class Repository and Language Bindings

+-+ +-----+ +-------+ +---+ +---------+
]C] ]Cobol] ]Fortran] ]C++] ]Smalltalk]
+-+ +-----+ +-------+ +---+ +---------+
 ]     ]        ]       ]        ]
 V     V        V       V        V  ... etc
+------------------------------------------+
]       SOM Run-Time Class Repository      ]
+------------------------------------------+
 ]     ]        ]       ]        ]  ... etc
 V     V        V       V        V
+-+ +-----+ +-------+ +---+ +---------+
]C] ]Cobol] ]Fortran] ]C++] ]Smalltalk]
+-+ +-----+ +-------+ +---+ +---------+

The box in Figure 1 with C pointing to the Run-Time Repository represents a binding which allows classes to be defined in C and added to the SOM run-time repository. The box from the run-time repository to C is a binding which allows C to use classes from the repository regardless of the language in which the classes were originally written. When we say "use a class", we mean either instantiating and invoking methods on objects of a class, or deriving new classes using that class as a base class.

In the current version of OS/2 2.0, we support only the C language bindings. The other languages shown in figure 1 are for illustration only. This is neither a complete list of languages under consideration nor a committed list. We are working with a wide variety of language suppliers, both internally and externally, to make this list as complete as possible.

As we discussed in the Winter issue, the C bindings allow object-oriented programs to be developed much like they are developed in C++. However in contrast to C++, SOM allows classes to be used by a wide variety of languages as new language bindings become available. SOM also solves other weaknesses in C++ when it comes to developing class libraries. For a good introduction to C++ and these library issues, see Class Construction in C and C++ (Sessions, 92).

Classes in SOM

Lets reconsider a set of classes we first looked at in the winter issue. We will start with the Student class. An object of type Student knows how to set up its id and name. It knows how to return its ID. Finally, it knows how to print itself. The class definition file for Student is shown in Figure 2.

Figure 2. Student class definition

include <somobj.sc>
class:
  Student;
parent:
  SOMObject;
data:
  char  idU16e;      /* student id */
  char  nameU32e;    /* student name */
methods:
  override  somInit;
  void  setUpStudent(char *id, char *name);
  void  printStudentInfo();
  char  *getStudentType();
  char  *getStudentId();

The class implementation file for Student is shown in Figure 3. Recall from our last article that most of the class implementation file is produced automatically by the SOM compiler. Those lines shown in bold face are the only lines the class implementor actually needs to write.

Figure 3. Student class implementation (Programmer added lines shown in bold type)

#define Student_Class_Source
#include "student.ih"

SOM_Scope void SOMLINK somInit(Student *somSelf)
{
  StudentData *somThis = StudentGetData(somSelf);
  parent_somInit(somSelf);
  _idU0e = _nameU0e = '\0';                          <--
}
SOM_Scope void SOMLINK setUpStudent(Student *somSelf,
    char *id, char *name)
{
  StudentData *somThis = StudentGetData(somSelf);
  strcpy(_id, id);                                   <--
  strcpy(_name, name);                               <--
}
SOM_Scope void   SOMLINK printStudentInfo(Student *somSelf)
{
  StudentData *somThis = StudentGetData(somSelf);
  printf("\n    Id         : %s \n", _id);           <--
  printf("    Name       : %s \n", _name);           <--
  printf("    Type       : %s \n", _getStudentType(somSelf));
}
SOM_Scope char *  SOMLINK getStudentType(Student *somSelf)
{
  StudentData *somThis = StudentGetData(somSelf);
  static char *type = "student";                     <--
  return (type);                                     <--
}
SOM_Scope char *  SOMLINK getStudentId(Student *somSelf)
{
  StudentData *somThis = StudentGetData(somSelf);
  return (_id);                                      <--
}

Given this definition of Student, we can derive a new class, say GraduateStudent, which is just like a student, but has information about a thesis and a degree. The class definition file for GraduateStudent is shown in Figure 4, and the class implementation file is shown in Figure 5.

Figure 4. GraduateStudent class definition file.

include "student.sc"
class:
  GraduateStudent;
parent:
  Student, local;
data:
  char  thesisU128e;    /* thesis title */
  char  degreeU16e;     /* graduate degree type */
methods:
  override  somInit;
  override  printStudentInfo;
  override  getStudentType;
  void  setUpGraduateStudent(char *id, char *name,
    char *thesis, char *degree);

Figure 5. GraduateStudent class implementation file. (Programmer added lines shown in bold type.)

#define GraduateStudent_Class_Source
#include "graduate.ih"

SOM_Scope void   SOMLINK somInit(GraduateStudent *somSelf)
{
  GraduateStudentData *somThis =
     GraduateStudentGetData(somSelf);
  parent_somInit(somSelf);
  _thesisU0e = _degreeU0e = '\0';                    <--
}
SOM_Scope void   SOMLINK printStudentInfo(
  GraduateStudent *somSelf)
{
  GraduateStudentData *somThis =
    GraduateStudentGetData(somSelf);
  parent_printStudentInfo(somSelf);
  printf("    Thesis     : %s \n", _thesis);         <--
  printf("    Degree     : %s \n", _degree);         <--
}
SOM_Scope char *  SOMLINK getStudentType(
  GraduateStudent *somSelf)
{
  GraduateStudentData *somThis =
    GraduateStudentGetData(somSelf);
  static char *type = "Graduate";                    <--
  return (type);                                     <--
}
SOM_Scope void   SOMLINK setUpGraduateStudent(
  GraduateStudent *somSelf, char *id, char *name,
  char *thesis, char *degree)
{
  GraduateStudentData *somThis =
     GraduateStudentGetData(somSelf);
  _setUpStudent(somSelf,id,name);                    <--
  strcpy(_thesis, thesis);                           <--
  strcpy(_degree, degree);                           <--
}

With these two classes defined and implemented, we can write client code to instantiate and manipulate <Student>s and <GraduateStudent>s. The program shown in Figure 6 instantiates two <Student>s and two <GraduateStudent>s, initializes the objects with data, and asks the objects to print themselves.

Figure 6. Client Program For <Student> and <GraduateStudent>

Program:
#include "graduate.h"

main()
{
  Student *student1 = StudentNew();
  Student *student2 = StudentNew();
  GraduateStudent *grad1 = GraduateStudentNew();
  GraduateStudent *grad2 = GraduateStudentNew();

  _setUpStudent(student1,"120455","Joe Doe");
  _setUpStudent(student2,"103606","Mary Smith");
  _setUpGraduateStudent(grad1,"203230","Janet Brown",
                        "Parser Generators", "M.S.");
  _setUpGraduateStudent(grad2,"240900","Mark Black",
                        "Code Optimization", "Ph.D.");

  _printStudentInfo(student1);
  _printStudentInfo(student2);
  _printStudentInfo(grad1);
  _printStudentInfo(grad2);
}

Output:
    Id         : 120455
    Name       : Joe Doe
    Type       : student

    Id         : 103606
    Name       : Mary Smith
    Type       : student

    Id         : 203230
    Name       : Janet Brown
    Type       : Graduate
    Thesis     : Parser Generators
    Degree     : M.S.

    Id         : 240900
    Name       : Mark Black
    Type       : Graduate
    Thesis     : Code Optimization
    Degree     : Ph.D.

Class Objects

Every class with at least one instantiated object has exactly one associated class object. Every instantiated object maintains a pointer to its class object which it can return through the method somGetClass. This method is inherited from SOMObject, a class from which every class is derived, either directly or indirectly. In the program shown in Figure 6, student1 and student2 are both objects of class Student, and therefore both share the same class object. Similarly grad1 and grad2 are both objects of class GraduateStudent, and therefore both share another class object, different than the class object shared by student1 and student2. This is shown pictorially in Figure 7.

Figure 7. Relationship between objects and class objects

+--------+                                       +-----+
]student1]---> +-------+   +---------------+ <---]grad1]
+--------+     ]Student]   ]GraduateStudent]     +-----+
               ]class  ]   ]class          ]
+--------+     ]object ]   ]object         ]     +-----+
]student2]---> +-------+   +---------------+ <---]grad2]
+--------+                                       +-----+

Another way to access a class object is through the SOM defined macro _classname. For Student, this macro is _Student. This macro returns a pointer to the appropriate class object, if it exists, or zero, if it does not exist. SOM instantiates the class object the first time an object of its controlled class is instantiated. The _Student will, therefore, return 0 if and only if no Student objects have yet been instantiated.

The class object is quite a useful object. The class of a class object is either SOMClass or, as we will see later, some class derived from SOMClass. There are a variety of methods defined for SOMClass, and these are all documented in the class definition file for SOMClass, somcls.sc and described in the SOM documentation (SOM). There are methods which can tell you the size the class, the parent of the class, whether the class is derived from some other class, and whether the class supports a specific method, to name a few.

One of the SOMClass methods is somGetName(), which returns a pointer to a character string containing the name of the class for which this is the class object. For the Student class object, this string would be "Student".

Another interesting SOMClass method is somNew(), which returns a newly instantiated object of the appropriate class. For the Student class object, the newly instantiated object would be of the Student class. The method somNew() is always invoked to instantiate new objects. Many programmers are not aware of this because they use a macro wrapper of the form classnameNew, for example, StudentNew(). This wrapper first makes sure the appropriate class object exists, and then passes through the instantiation request via somNew().

In most cases, we would instantiate objects using the class instantiation macro, say StudentNew(), but there might be cases when we can access the class object but not the class instantiation macro. One such example might be a function which accepts a pointer to any object, and returns another newly instantiated object of the same class. Figure 8 modifies the client program shown in Figure 6 to make use of the Student and GraduateStudent class objects and their somGetClass() and somNew() methods.

Figure 8. Client Program Using Class Object

#include "graduate.h"

SOMAny *createObject(SOMAny *object)
{
  return(_somNew(_somGetClass(object)));
}

main()
{
  Student *student1 = StudentNew();
  GraduateStudent *grad1 = GraduateStudentNew();
  Student *student2;
  GraduateStudent *grad2;

  student2 = createObject(student1);
  grad2 = createObject(grad1);

  _setUpStudent(student1,"120455","Joe Doe");
  _setUpStudent(student2,"103606","Mary Smith");
  _setUpGraduateStudent(grad1,"203230","Janet Brown",
                        "Parser Generators", "M.S.");
  _setUpGraduateStudent(grad2,"240900","Mark Black",
                        "Code Optimization", "Ph.D.");

  _printStudentInfo(student1);
  _printStudentInfo(student2);
  _printStudentInfo(grad1);
  _printStudentInfo(grad2);
}

Several of the SOMClass methods have passthrough methods defined in SOMObject. In those cases, the actual code for the passthrough methods just gets the object's class object, and passes through the call using the appropriate SOMClass method. For example, the SOMObject method somGetClassName() passes through to the SOMClass method somGetName(). In this article we will use either the SOMObject methods or the SOMClass passthrough, depending on the point we are making.

The Class of The Class Object

Every object in SOM is associated with a class. The class of student is Student, which we can see from this program:

#include "student.h"

main()
{
  Student *student = StudentNew();
  printf("student object is of <%s> class\n",
          _somGetClassName(student));
}

which gives this output:

student object is of <Student> class

The class objects are also associated with a class. The class of any class object is by default SOMClass. The class SOMClass is, like all classes, derived from SOMObject, and therefore supports all of the SOMObject methods. We can, for example, verify the class of the <Student> class object as in the following program:

#include "student.h"

main()
{
  Student *student = StudentNew();
  SOMClass *studentClassObject;

  studentClassObject = _somGetClass(student);
  printf("student class object is of <%s> class\n",
          _somGetClassName(studentClassObject));
}

giving this output:

student class object is of <SOMClass> class

We use the word metaclass to describe the class of an objects' class object. Since the class of the student's class object is SOMClass, we say the metaclass of Student is SOMClass. Don't confuse class with metaclass. The class of student is Student. The metaclass of student is SOMClass.

We can change the metaclass of a given class by a two stage process:

  1. Derive a new class from SOMClass, either directly or indirectly.
  2. Tell the given class that its class object will be of the new type through the metaclass directive.

There are at least three reasons one might want to change the class of a class object. The first is to add new methods for initializing new objects. Such methods are referred to as constructor methods. The second is to modify how memory is allocated for objects. The third is to keep track of global information about the class, such as how many objects have been instantiated.

Lets go through the steps necessary to change the class of the Student class object from SOMClass to StudentFactory, or, in other words, changing the metaclass of student from SOMClass to Studentfactory. First, we define the StudentFactory to be derived from SOMClass. This class will add one new method to those found in SOMClass. The new method will be countObjects(). We will also override the client invoked SOMClass methods somNew(), which instantiates a new object. We also need to override the somInit() method invoked on a newly instantiated class object, to initialize the count to zero. The class definition and implementation files for StudentFactory are shown in Figure 9.

Figure 9: Class Definition and Implementation Files for StudentFactory

Class Definition File:
include <somobj.sc>

class:
  StudentFactory;
parent:
  SOMClass;
data:
  int count;
methods:
  override somInit;
  override somNew;
  int countObjects();

Class Implementation File:
#define StudentFactory_Class_Source
#include "countmet.ih"
SOM_Scope void   SOMLINK somInit(StudentFactory *somSelf)
{
    StudentFactoryData *somThis = StudentFactoryGetData(somSelf);
   parent_somInit(somSelf);
    _count = 0;
}
SOM_Scope SOMAny *  SOMLINK somNew(StudentFactory *somSelf)
{
    StudentFactoryData *somThis = StudentFactoryGetData(somSelf);
   _count ++;
    return (parent_somNew(somSelf));
}
SOM_Scope int   SOMLINK countObjects(StudentFactory *somSelf)
{
    StudentFactoryData *somThis = StudentFactoryGetData(somSelf);
   return (int) _count;
}

We now modify the student class definition files as shown in Figure 10.

Figure 10: Newly Modified student class definition files (Modified lines shown in bold face.)

include <somobj.sc>
include "countmet.sc"

class:
  Student;
metaclass:                                           <--
  StudentFactory, local;                             <--
parent:
  SOMObject;
data:
  char  idU16e;      /* student id */
  char  nameU32e;    /* student name */
methods:
  override  somInit;
  void  setUpStudent(char *id, char *name);
  void  printStudentInfo();
  char  *getStudentType();
  char  *getStudentId();

No changes are needed to the class implementation file for <Student>.

We can now use our new StudentFactory object to find out how many student objects have been instantiated, as shown in this program:

#include "student.h"

main()
{
  Student *student1 = StudentNew();
  Student *student2 = StudentNew();
  SOMClass *studentClassObject;

  _setUpStudent(student1,"120455","Joe Doe");
  _setUpStudent(student2,"103606","Mary Smith");

  studentClassObject = _somGetClass(student1);
  printf("Student count: %d \n",
    _countObjects(studentClassObject));
  printf("student1 class object is of <%s> class\n",
    _somGetClassName(studentClassObject));
}

giving this output:

Student count: 2
student1 class object is of <StudentFactory> class

Implied Metaclass

Given a new class for class objects, we can have any number of classes associated with the new class object. For example, instead of StudentFactory we might have used the metaclass name CountFactory to indicate greater generality, and then used this metaclass whenever we want to keep track of total instantiated objects.

Often we do not need such generality and we only intend for a given class object to be associated with one class. For example, the only change to the metaclass might be the addition of new constructor methods which are only applicable to a specific class. In such cases we can use a slight short cut to redefine the metaclass. This short cut is called implied metaclass. The main advantage of implied metaclasses is that the class definition file for the metaclass can be folded into the class definition file for the class it controls, and similarly for the class implementation file.

The student implementation file rewritten to use the implied metaclass is shown in Figure 11. The student implementation file rewritten to use the implied metaclass is shown in Figure 12.

Figure 11. Student Class Definition using implied Metaclass (Changes from original <Student> shown in bold face.)

include <somobj.sc>

class:
  Student, classprefix = StudentClass_;            <--
parent:
  SOMObject;
data:
  char  idU16e;      /* student id */
  char  nameU32e;    /* student name */
  int   count, class;                              <--
methods:
  override  somInit;
  void  setUpStudent(char *id, char *name);
  void  printStudentInfo();
  char  *getStudentType();
  char  *getStudentId();
  override somInit, class;                         <--
  override somNew, class;                          <--
  int      countObjects(), class;                  <--

Notice there are two new keywords used to define implied metaclasses. The keyword "classprefix" indicates a prefix used to identify methods associated with the class object. The keyword "class" is used to identify data members or methods associated with the class object.

Figure 12. Student Class Implementation using implied Metaclass (Programmer added lines shown in bold face.)

#define Student_Class_Source
#include "student.ih"

SOM_Scope void   SOMLINK somInit(Student *somSelf)
{
    StudentData *somThis = StudentGetData(somSelf);
    parent_somInit(somSelf);
    _idU0e = _nameU0e = '\0';                          <--
}
/* Other Student Methods, as before, followed by... */
#undef SOM_CurrentClass
#define SOM_CurrentClass SOMMeta

SOM_Scope void SOMLINK StudentClass_somInit(
    M_Student *somSelf)
{
    M_StudentData *somThis = M_StudentGetData(somSelf);
    parent_somInit(somSelf);
    _count = 0;                                         <--
}
SOM_Scope SOMAny *SOMLINK StudentClass_somNew(
    M_Student *somSelf)
{
    M_StudentData *somThis = M_StudentGetData(somSelf);
    _count ++;                                           <--
    return (parent_somNew(somSelf));
}
SOM_Scope int SOMLINK StudentClass_countObjects(
    M_Student *somSelf)
{
    M_StudentData *somThis = M_StudentGetData(somSelf);
    return (int) _count;                                  <--
}

Our client program, shown again here, needs no changes:

#include "student.h"

main()
{
  Student *student1 = StudentNew();
  Student *student2 = StudentNew();
  SOMClass *studentClassObject;

  _setUpStudent(student1,"120455","Joe Doe");
  _setUpStudent(student2,"103606","Mary Smith");

  studentClassObject = _somGetClass(student1);
  printf("Student count: %d \n",
    _countObjects(studentClassObject));
  printf("student1 class object is of <%s> class\n",
    _somGetClassName(studentClassObject));
}

The output, which had looked like:

Student count: 2
student1 class object is of <StudentFactory> class

now looks like:

Student count: 2
student1 class object is of <M_Student> class

The difference in output reflects the system assigned name of the metaclass.

Summary

The class object is an important source of runtime information in SOM. Virtually anything that one might want to know about a class can be found out through one of the class object's methods. The class object is itself a fully functional object, like any other object in SOM. It has its own class, by default SOMClass which can be modified using any of the normal class modification techniques including inheritance and polymorphism.

The class object is an important programmer resource. It is the source of runtime information about classes and gives the ability to make runtime decisions about how objects will be manipulated. Because the class object is a standard SOM object, instantiated from a standard SOM Class, you have considerable flexibility to redefine its characteristics as needed.

References

  • Sessions, Roger: Class Construction in C and C++: Object-Oriented Programming Fundamentals, Prentice Hall, Englewood Cliffs, New Jersey, 1992 (IBM Doc. S242-0086). [1]
  • Sessions, Roger and Nurcan Coskun: Object-Oriented Programming in OS/2 2.0 Using SOM. IBM Personal Systems Developer (Winter 1992): 107-120.
  • SOM: OS/2 2.0 Technical Library System Object Model Guide and Reference, Prentice Hall, 1992 (IBM Doc. 10G6309) [2]

Acknowledgements

SOM is the work of many people. Mike Conner developed the initial idea and implementation, and continues to lead the overall design of SOM. Andy Martin designed the SOM Class Interface Language, and designed and implemented the class Interface compiler. Larry Raper implemented many features of the run time library and porteed SOM to OS/2. Larry Loucks provided close technical tracking and was instrumental in focusing the effort. Other SOM developers include Nurcan Coskun, Scott Danforth, Hari Madduri, Roger Sessions, Simon Nash, and John Wang. The project is managed by Gerry Ronga.