home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 14 Text / 14-Text.zip / SOMINT.ZIP / SOMINTRO.TXT
Text File  |  1992-12-02  |  36KB  |  913 lines

  1. Object-Oriented Programming in OS/2 2.0
  2. by
  3. Roger Sessions
  4. Nurcan Coskun
  5. --------------------------------------------------------
  6. Author Contact Information
  7. Roger Sessions AUSVM1(SESSIONS) tieline 678-8085
  8. Nurcan Coskun AUSVM1(NURCAN) tieline 678-8073
  9. --------------------------------------------------------
  10.  
  11. IBM Personal Systems Developer, Winter 1991, Copyright 1991 by
  12. INTERNATIONAL BUSINESS MACHINES CORPORATION.
  13.  
  14. ABSTRACT
  15. Object-Oriented Programming is quickly establishing itself as an
  16. important methodology in developing high quality, reusable code.
  17. In the 2.0 release of OS/2, IBM is introducing a new system for
  18. developing class libraries and Object-Oriented programs.  This
  19. system is called SOM for System Object Model.  This paper gives a
  20. general introduction to the Object-Oriented Paradigm, discusses
  21. developing Object-Oriented class libraries using SOM, and
  22. compares SOM libraries to those developed using standard Object-
  23. Oriented languages.
  24.  
  25. INTRODUCTION TO OBJECT-ORIENTED PROGRAMMING
  26. The latest revolution to hit the software community is Object-
  27. Oriented Programming.  Object-Oriented Programming Languages
  28. (OOPL) are being used throughout the industry, Object-Oriented
  29. Databases (OODB) are starting elicit widespread interest, and
  30. even Object-Oriented Design and Analysis (OODA) tools are
  31. changing the way people design and model systems.
  32.  
  33. Object-Oriented Programming is best understood in contrast to its
  34. close cousin, Structured Programming.  Both attempt to deal with
  35. the same basic issue, managing the complexity of ever more
  36. complex software systems.
  37.  
  38. Structured Programming models a system as a layered set of
  39. functional modules.  These modules are built up in a pyramid like
  40. fashion, each layer representing a higher level view of the
  41. system.  Structured Programming models the system's behavior, but
  42. gives little guidance to modeling the system's information.
  43.  
  44. Object-Oriented Programming models a system as a set of
  45. cooperating objects.  Like Structured Programming, it tries to
  46. manage the behavioral complexity of a system.  Object-Oriented
  47. Programming, however, goes beyond Structured Programming in also
  48. trying to manage the informational complexity of a system.
  49.  
  50. Because Object-Oriented Programming models both the behavioral
  51. and informational complexity of a system, the system tends to be
  52. much better organized than if it was simply well "structured".
  53. Because Object-Oriented systems are better organized, they are
  54. easier to understand, debug, maintain, and evolve.  Well
  55. organized systems also lend themselves to code reuse.
  56.  
  57. Object-Oriented Programming sees the dual issues of managing
  58. informational and behavioral complexity as being closely related.
  59. Its basic unit of organization is the object.  Objects have some
  60. associated data, which we call the object's state, and a set of
  61. behaviors, which we call the object's methods.  A class is a
  62. general description of an object, which defines the data which
  63. represents the object's state, and the methods the object
  64. supports.
  65.  
  66. OBJECT-ORIENTED PROGRAMMING IN C
  67. Before we examine SOM, let's consider Object-Oriented Programming
  68. in C; this will lead us naturally into the SOM philosophy.  The
  69. techniques in this section as well as many related advanced C
  70. coding techniques are discussed in the book Reusable Data
  71. Structures for C [Sessions, 89].
  72.  
  73. Consider a data structure definition containing information
  74. related to a generic stack.  We may have a series of functions
  75. all designed to operate on our stack structure.  Given a basic
  76. stack definition, we may have multiple instances of this
  77. structure declared within our program.
  78.  
  79. Our generic stack definition, in C, might look like
  80.  
  81. struct stackType {
  82.   void *stackArray[STACK_SIZE];
  83.   int stackTop;
  84. };
  85. typedef struct stackType Stack;
  86.  
  87. We could define some generic stack functions, say
  88.  
  89. Stack *create();       /* malloc and initialize a new stack. */
  90. void *pop(             /* Pop element off stack. */
  91.   Stack *thisStack);
  92. void push(             /* Push new element onto stack. */
  93.   Stack *thisStack,
  94.   void *nextElement);
  95.  
  96. Most C programmers can imagine how such functions would be
  97. written.  The push() function, for example, would look like
  98.  
  99. void push(Stack *thisStack, void *nextElement)
  100. {
  101.   thisStack->stackArray[thisStack->stackTop] = nextElement;
  102.   thisStack->stackTop++;
  103. }
  104.  
  105. A client program might use this stack to, say, create a stack of
  106. words needing interpretation:
  107.  
  108. main()
  109. {
  110.   Stack *wordStack;
  111.  
  112.   char *subject = "Emily";
  113.   char *verb = "eats";
  114.   char *object = "ice cream";
  115.   char *nextWord;
  116.  
  117.   wordStack = create();
  118.   push(wordStack, object);
  119.   push(wordStack, verb);
  120.   push(wordStack, subject);
  121.  
  122.   /* ... */
  123.   while (nextWord = pop(wordStack)) {
  124.     printf("%s\n", nextWord);
  125.     /* ... */
  126.   }
  127. }
  128.  
  129. Using this example, let's look at the language of Object-Oriented
  130. Programming.  A class is a definition of an object.  The
  131. definition includes the data elements of the object and the
  132. methods it supports.  A stack is an example of a class.  We say
  133. that a stack contains two data elements (stackArray and
  134. stackTop), and supports three methods, create(), push(), and
  135. pop().  A method is like a function, but is designed to operate
  136. on an object of a particular class.  An object is a specific
  137. instance, or instantiation, of a class.  We say wordStack is an
  138. object of class Stack, or wordStack is an instance of a stack.
  139.  
  140. Every method needs to know the specific object on which it is to
  141. operate.  We call this object the target object, or sometimes the
  142. receiving object.  Notice that each method (except create())
  143. takes as its first parameter a pointer to the target object.
  144. This is because a program may have many objects of a given class,
  145. and each are potential targets for the class methods.
  146.  
  147. There are three important advantages of this type of
  148. organization.  First, we are developing some generic concepts,
  149. which can be reused in other situations in which similar concepts
  150. are appropriate.  Second, we are developing self-contained code,
  151. which can be fully tested before it is folded into our program.
  152. Third, we are developing encapsulated code, the internal details
  153. of which are hidden and of no interest to the client.  Our client
  154. main() program need know nothing about the Stack class other than
  155. its name, the methods it supports,  and their interfaces.
  156.  
  157. INTRODUCTION TO SOM
  158. OS/2 2.0 includes a language-neutral Object-Oriented programming
  159. mechanism called SOM (for System Object Model).  Although it is
  160. possible to write Object-Oriented programs in traditional
  161. languages, such as we did with the stack example, SOM is
  162. specifically designed to support the new paradigm and to be
  163. usable with both procedural (or non Object-Oriented) languages
  164. and Object-Oriented languages.
  165.  
  166. A major claim of Object-Oriented programming is code reusability.
  167. This is most often achieved through the use of class libraries.
  168. Today's library technology is limited in that these class
  169. libraries are always language specific.  A C++ library cannot be
  170. used by a Smalltalk programmer, and visa versa.  Clearly there is
  171. a need to create a language-neutral object model, one which can
  172. be used to create class libraries usable from any programming
  173. language, procedural or Object-Oriented.  SOM is designed to
  174. address this need.
  175.  
  176. SOM introduces three important features lacking in most
  177. procedural languages.  These are encapsulation, inheritance, and
  178. polymorphism (referred to here as "override resolution").
  179.  
  180. Encapsulation means the ability to hide implementation details
  181. from clients.  This protects clients from changes in our
  182. implementation, and protects our implementation from tinkering by
  183. clients.  Our stack example was not protected.  Although clients
  184. did not need to know the internal data structures of the stack,
  185. we had no way to prevent clients from looking at such
  186. implementation details.  We could discourage, but not prevent,
  187. clients from writing code which used, and possibly corrupted,
  188. internal stack data elements.
  189.  
  190. Inheritance, or class derivation, is a specific technique for
  191. developing new classes from existing classes.  It allows one to
  192. create new classes which are more specialized versions of
  193. existing classes.  For example, we could create a
  194. DebuggableStack, which is like a Stack class, but supports
  195. further debugging methods, such as peek() and dump().
  196.  
  197. Inheritance also allows code consolidation.  If we have a class
  198. defining GraduateStudent and UnderGraduateStudent, we can
  199. consolidate common code into a third class, Student.  We then
  200. define GraduateStudent and UnderGraduate as more specialized
  201. classes, both derived from the common parent Student.
  202.  
  203. Inheritance introduces some additional semantics beyond those we
  204. have already examined.  A specialized class is said to be derived
  205. from a more generalized class.  The general class is called the
  206. parent class, or sometimes, the base class.  The specialized
  207. class is called the child class, or sometimes, the derived class.
  208. A child class is said to inherit the characteristics of its
  209. parent class, meaning that any methods defined for a parent are
  210. automatically defined for a child.  Thus because GraduateStudent
  211. and UnderGraduateStudent are both derived from Student, they both
  212. automatically acquire any methods declared in their common
  213. parent.
  214.  
  215. Override resolution means invoked methods are resolved based not
  216. only on the name of the method, but also on a class's place
  217. within a class hierarchy.  This allows us to redefine methods as
  218. we derive classes.  We might define a printStudentInfo() method
  219. for Student and then override, or redefine, the method in both
  220. UnderGraduateStudent, and GraduateStudent.  Override resolution
  221. means that the method is resolved based on the type of the target
  222. object.  If the target object type is a Student, the Student
  223. version of printStudentInfo() is invoked.  If the target object
  224. type is a GraduateStudent, the GraduateStudent version of
  225. printStudentInfo() is invoked.
  226.  
  227. We will now look at SOM in more detail by examining how classes
  228. are defined in SOM, how SOM methods are written in the C
  229. programming language, and how clients use SOM classes.  SOM will
  230. eventually allow developers to write methods in a variety of
  231. languages including the popular Object-Oriented programming
  232. languages.  In OS/2 2.0, SOM support is limited to C, thus the
  233. language used in the examples.
  234.  
  235. DEFINING CLASSES IN SOM
  236. The process of creating class libraries in SOM is a three step
  237. process.  The class designer defines the class interface,
  238. implements the class methods, and finally loads the resulting
  239. object code into a class library.  Clients either use these
  240. classes directly, make modifications to suit their specific
  241. purposes, or add entirely new classes of their own.
  242.  
  243. In SOM we define a class by creating a class definition file.  We
  244. will give a basic example here, and defer more detailed
  245. discussion of the many keywords and options to the SOM manuals
  246. [SOM].
  247.  
  248. The class definition file is named with an extension of "csc".
  249. In its most basic form, the class definition file is divided into
  250. the following sections:
  251.  
  252.   1. Include section
  253.      This section declares files which need to be included, much
  254.      like the C #include directive.
  255.   2. Class name and options
  256.      This section defines the name of the class and declares
  257.      various options.
  258.   3. Parent information
  259.      This defines the parent, or base, class for this class.  All
  260.      classes must have a parent.  If your class is not derived
  261.      from any of your own classes, than it's parent will be the
  262.      SOM defined class SOMObject, the class information of which
  263.      is in the file somobj.sc.
  264.   4. Data Section
  265.      This section declares any data elements contained by objects
  266.      of this class.  By default, data can be accessed only by
  267.      methods of the class.
  268.   5. Methods Section
  269.      This section declares methods to which objects of this class
  270.      can respond.  By default, all methods declared in this
  271.      section are available to any class client.
  272.  
  273. Comments can be used for documentation purposes, and the
  274. following styles are all acceptable:
  275.  
  276. /* This is a comment. */
  277. // This is a comment.
  278. -- This is a comment.
  279.  
  280. The class definition file, student.csc, describes a non-derived
  281. Student class, and is shown in figure 1.
  282.  
  283. ((start figure 1, caption: Class Definition File: student.csc))
  284. include <somobj.sc>
  285.  
  286. class:
  287.   Student;
  288.  
  289. -- "Student" class provides a base class to generate more
  290. -- specialized students like "GraduateStudent" and
  291. -- "UnderGraduateStudent".
  292.  
  293. parent:
  294.   SOMObject;
  295.  
  296. data:
  297.   char  id[16];      /* student id */
  298.   char  name[32];    /* student name */
  299.  
  300. methods:
  301.  
  302.   void  setUpStudent(char *id, char *name);
  303.   -- sets up a new student.
  304.  
  305.   void  printStudentInfo();
  306.   -- prints the student information.
  307.  
  308.   char  *getStudentType();
  309.   -- returns the student type.
  310.  
  311.   char  *getStudentId();
  312.   -- returns the student id.
  313. ((end table))
  314.  
  315. WRITING METHODS
  316. Class methods are implemented in the class method implementation
  317. file.  Each method defined in the method section of the class
  318. definition file needs to be implemented.  They can be implemented
  319. in any language that offers SOM support, which for now is only C.
  320. The student class method implementation file, student.c, is shown
  321. in figure 2.
  322.  
  323. ((start figure 2, caption: Class Method Implementation File:
  324. student.c))
  325. #define Student_Class_Source
  326. #include "student.ih"
  327.  
  328. static void setUpStudent(
  329.     Student *somSelf, char *id, char *name)
  330. {
  331.     StudentData *somThis = StudentGetData(somSelf);
  332.     strcpy(_id, id);
  333.     strcpy(_name, name);
  334. }
  335. static void printStudentInfo(Student *somSelf)
  336. {
  337.     StudentData *somThis = StudentGetData(somSelf);
  338.     printf("    Id         : %s \n", _id);
  339.     printf("    Name       : %s \n", _name);
  340.     printf("    Type       : %s \n", _getStudentType(somSelf));
  341. }
  342. static char *getStudentType(Student *somSelf)
  343. {
  344.     StudentData *somThis = StudentGetData(somSelf);
  345.     static char *type = "student";
  346.     return (type);
  347. }
  348. static char *getStudentId(Student *somSelf)
  349. {
  350.     StudentData *somThis = StudentGetData(somSelf);
  351.     return (_id);
  352. }
  353. ((end figure 2))
  354.  
  355. Notice that the method code looks much like standard C, with a
  356. few differences.
  357.  
  358. First, each method takes, as its first parameter, a pointer
  359. (somSelf) to the target object.  This is very similar to our C
  360. stack implementation.  This parameter is implicit in the class
  361. definition file, but is made explicit in the method
  362. implementation.
  363.  
  364. Second, each method starts with a line setting an internal
  365. variable named somThis, which is used by macros within the SOM
  366. header file.
  367.  
  368. Third, names of data elements of the target object are preceded
  369. by an underscore character.  The underscored name turns into a C
  370. language macro defined in the class header file, part of the
  371. package SOM offers to shield method developers from the details
  372. of memory layout.
  373.  
  374. Fourth, methods are invoked using an underscored syntax.  This
  375. underscored name turns into a macro invocation which shields
  376. programmers from having to understand the details of method
  377. resolution.
  378.  
  379. The first parameter of every method is always a pointer to the
  380. target object.  This can be seen in the method printStudentInfo()
  381. which invokes the method getStudentType() on its own target
  382. object.
  383.  
  384. The process of creating a class method implementation file can be
  385. greatly speeded up by the SOM compiler, which creates a valid C
  386. method implementation file lacking only the body of the methods.
  387. The body is then filled in by the class implementor. For the
  388. student example, the SOM compiler would create a file similar to
  389. the one shown in figure 3.
  390.  
  391. ((start figure 3, caption: SOM compiler generated student.c))
  392. #define Student_Class_Source
  393. #include "student.ih"
  394.  
  395. static void setUpStudent(
  396.     Student *somSelf, char *id, char *name)
  397. {
  398.     StudentData *somThis = StudentGetData(somSelf);
  399. }
  400. static void printStudentInfo(Student *somSelf)
  401. {
  402.     StudentData *somThis = StudentGetData(somSelf);
  403. }
  404. /* ...and so on for the other methods. */
  405. ((end figure 3))
  406.  
  407. MECHANICS OF USING SOM
  408. There is a set of files involved with each class.  Here we will
  409. look at the most important of these files and discuss their
  410. purpose and how they are created.  They have different
  411. extensions, but all have the same filename as the class
  412. definition file, Student in our example.  The SOM compiler
  413. generates files based on the value of an environment variable, as
  414. described in the SOM users guide [SOM].  These files are
  415. described in table 1.
  416.  
  417. ((start table 1, caption: Student Class Files))
  418. student.csc - This is the class definition file, as described
  419. earlier.
  420.  
  421. student.sc - This is a subset of the class definition file.  It
  422. includes all information from the .csc file which is public,
  423. including comments on public elements.  For the student example,
  424. student.sc would include everything from student.csc except the
  425. data section.  This file is created by the SOM compiler, and
  426. although human readable, should not be edited, as it will be
  427. regenerated whenever changes are made to the .csc file.
  428.  
  429. student.h - This is a valid C header file which contains macros
  430. necessary to invoke public methods and access public data
  431. elements of the class.  This file will be included in any client
  432. of the class.  This file is created by the SOM compiler, and is
  433. normally only read by programmers who need to know how method
  434. resolution is implemented.  This file should not be edited.
  435.  
  436. student.ih - Similar to student.h, but contains additional
  437. information needed for implementing methods.  This is the
  438. implementor's version of the .h file, and must be included in the
  439. class methods implementation file.  This file is created by the
  440. SOM compiler and should not be edited.
  441.  
  442. student.c - Contains the method implementations.  This is
  443. initially created by the SOM compiler and then updated by the
  444. class implementor.
  445. ((end table1)
  446.  
  447. BUILDING SOM CLASSES FROM OTHER CLASSES
  448. There are two ways to use classes as building blocks for other
  449. classes.  These are derivation (or inheritance) and construction.
  450. Let's consider derivation first.
  451.  
  452. In this example, GraduateStudent is derived from Student, its
  453. base, or parent class.  A derived class automatically picks up
  454. all characteristics of the base class.  A derived class can add
  455. new functionality through the definition and implementation of
  456. new methods.  A derived class can also redefine methods of its
  457. base class, a process called overriding.  GraduateStudent adds
  458. setUpGranduateStudent() to those methods it inherits from
  459. Student.  It overrides two other inherited methods,
  460. printStudentInfo() and getStudentType().  It inherits without
  461. change setUpStudent() and getStudentId() from the Student base
  462. class.
  463.  
  464. The class definition file for GraduateStudent, graduate.csc, is
  465. shown in figure 4.
  466.  
  467. ((start figure 4, caption: Class Definition File: graduate.csc))
  468.  
  469. include <student.sc>
  470.  
  471. class:
  472.   GraduateStudent;
  473.  
  474. parent:
  475.   Student;
  476.  
  477. data:
  478.   char  thesis[128];    /* thesis title */
  479.   char  degree[16];     /* graduate degree type */
  480.  
  481. methods:
  482.   override  printStudentInfo;
  483.   override  getStudentType;
  484.   void  setUpGraduateStudent(
  485.         char *id, char *name, char *thesis, char *degree);
  486. ((end figure 4))
  487.  
  488. The method implementation file, graduate.c, is shown in figure 5.
  489. ((start figure 5, caption: Class Method Implementation File:
  490. graduate.c))
  491.  
  492. #define GraduateStudent_Class_Source
  493. #include "graduate.ih"
  494.  
  495. static void printStudentInfo(GraduateStudent *somSelf)
  496. {
  497.     GraduateStudentData *somThis =
  498. GraduateStudentGetData(somSelf);
  499.     parent_printStudentInfo(somSelf);
  500.     printf("    Thesis     : %s \n", _thesis);
  501.     printf("    Degree     : %s \n", _degree);
  502. }
  503. static char *getStudentType(GraduateStudent *somSelf)
  504. {
  505.     static char *type = "Graduate";
  506.     return (type);
  507. }
  508. static void setUpGraduateStudent(
  509.     GraduateStudent *somSelf, char *id, char *name,
  510.     char *thesis, char *degree)
  511. {
  512.     GraduateStudentData *somThis =
  513. GraduateStudentGetData(somSelf);
  514.     _setUpStudent(somSelf,id,name);
  515.     strcpy(_thesis, thesis);
  516.     strcpy(_degree, degree);
  517. }
  518. ((end figure 5))
  519.  
  520. Often an overridden method will need to invoke the original
  521. method of its parent.  For example, the printStudentInfo() for
  522. GraduateStudent first invokes the Student version of
  523. printStudentInfo() before printing out the GraduateStudent
  524. specific information.  The syntax for this is
  525. "parent_MethodName", as can be seen in the printStudentInfo()
  526. method.
  527.  
  528. A given base class can be used for more than one derivation.  The
  529. class, UnderGraduateStudent, is also derived from Student.  The
  530. class definition file, undgrad.csc, is shown in figure 6.
  531.  
  532. ((start figure 6, caption: Class Definition File: undgrad.csc))
  533. include <student.sc>
  534.  
  535. class:
  536.   UnderGraduateStudent;
  537.  
  538. parent:
  539.   Student;
  540.  
  541. data:
  542.   char  date[16];     /* graduation date */
  543.  
  544. methods:
  545.   override  printStudentInfo;
  546.   override  getStudentType;
  547.   void  setUpUnderGraduateStudent(
  548.         char *id, char *name, char *date);
  549. ((end figure 6))
  550.  
  551. The method implementation file, undgrad.c, is shown in figure 7.
  552.  
  553. ((start figure 7, caption: Class Method Implementation File:
  554. undgrad.c))
  555.  
  556. #define UnderGraduateStudent_Class_Source
  557. #include "undgrad.ih"
  558.  
  559. static void printStudentInfo(
  560.     UnderGraduateStudent *somSelf)
  561. {
  562.     UnderGraduateStudentData *somThis =
  563.        UnderGraduateStudentGetData(somSelf);
  564.     parent_printStudentInfo(somSelf);
  565.     printf("    Grad Date  : %s \n", _date);
  566. }
  567. static char *getStudentType(UnderGraduateStudent *somSelf)
  568. {
  569.     static char *type = "UnderGraduate";
  570.     return (type);
  571. }
  572. static void setUpUnderGraduateStudent(
  573.     UnderGraduateStudent *somSelf,char *id, char *name, char
  574. *date)
  575. {
  576.     UnderGraduateStudentData *somThis =
  577.        UnderGraduateStudentGetData(somSelf);
  578.     _setUpStudent(somSelf,id,name);
  579.     strcpy(_date, date);
  580. }
  581. ((end figure 7))
  582.  
  583. The second technique for building classes is construction.  This
  584. means that a class uses another class, but not through
  585. inheritance.  A good example of construction is the class Course
  586. which includes an array of pointers to Students.  Each pointer
  587. contains the address of a particular student taking the course.
  588. We say that Course is constructed from Student.  The class
  589. definition file for Course, course.csc, is shown in figure 8.
  590.  
  591. ((start figure 8, caption: Class Definition File: course.csc))
  592. include <somobj.sc>
  593.  
  594. class:
  595.   Course;
  596.  
  597. -- "Course" class describes the interfaces required to setup the
  598. -- course information. The students are "Student" class type and
  599. -- can be added to or dropped from the courses through the
  600. -- "addStudent" and "dropStudent" methods.
  601.  
  602. parent:
  603.   SOMObject;
  604.  
  605. data:
  606.   char    code[8];         /* course code number */
  607.   char    title[32];       /* course title */
  608.   char    instructor[32];  /* instructor teaching */
  609.   int     credit;            /* number of credits  */
  610.   int     capacity;          /* maximum number of seats */
  611.   Student *studentList[20];/* enrolled student list */
  612.   int     enrollment;        /* number of enrolled students */
  613.  
  614. methods:
  615.   override  somInit;
  616.  
  617.   void  setUpCourse(char *code, char *title,
  618.      char *instructor, int credit, int capacity);
  619.   -- sets up a new course.
  620.  
  621.   int   addStudent(Student *student);
  622.   -- enrolls a student to the course.
  623.  
  624.   void  dropStudent(char *studentId);
  625.   -- drops the student from the course.
  626.  
  627.   void  printCourseInfo();
  628.   -- prints course information.
  629. ((end figure 8))
  630.  
  631. Often classes will want to take special steps to initialize their
  632. instance data.  An instance of Course must at least initialize
  633. the enrollment data element, to ensure the array index starts in
  634. a valid state.  The method somInit() is always called when a new
  635. object is created.  This method is inherited from SOMObject, and
  636. can be overridden when object initialization is desired.
  637.  
  638. This example brings up an interesting characteristic of
  639. inheritance, the "is-a" relationship between derived and base
  640. classes.  Any derived class can be considered as a base class.
  641. We say that a derived class "is-a" base class. In our example,
  642. any GraduateStudent "is-a" Student, and can be used anyplace we
  643. are expecting a Student.  The converse is not true.  A base class
  644. is not a derived class.  A Student can not be treated
  645. unconditionally as a GraduateStudent.  Thus elements of the array
  646. studentList can point to either Students, a GraduateStudents, or
  647. a UnderGraduateStudents.
  648.  
  649. The method implementation file for Course, course.c, is shown in
  650. figure 9.
  651.  
  652. ((start figure 9, caption: Class Method Implementation File:
  653. course.c))
  654. #define Course_Class_Source
  655. #include <student.h>
  656. #include "course.ih"
  657.  
  658. static void somInit(Course *somSelf)
  659. {
  660.     CourseData *somThis = CourseGetData(somSelf);
  661.     parent_somInit(somSelf);
  662.     _code[0] = _title[0] = _instructor[0] = '\0';
  663.     _credit = _capacity = _enrollment = 0;
  664. }
  665. static void setUpCourse(Course *somSelf, char *code,
  666.     char *title, char *instructor, int credit, int capacity)
  667. {
  668.     CourseData *somThis = CourseGetData(somSelf);
  669.     strcpy(_code, code);
  670.     strcpy(_title, title);
  671.     strcpy(_instructor, instructor);
  672.     _credit = credit;
  673.     _capacity = capacity;
  674. }
  675. static int addStudent(Course *somSelf, Student *student)
  676. {
  677.     CourseData *somThis = CourseGetData(somSelf);
  678.     if(_enrollment >= _capacity)  return(-1);
  679.     _studentList[_enrollment++] = student;
  680.     return(0);
  681. }
  682. static void dropStudent(Course *somSelf, char *studentId)
  683. {
  684.     int i;
  685.     CourseData *somThis = CourseGetData(somSelf);
  686.     for(i=0; i<_enrollment; i++)
  687.       if(!strcmp(studentId, _getStudentId(_studentList[i]))) {
  688.         _enrollment--;
  689.         for(i; i<_enrollment; i++)
  690.           _studentList[i] = _studentList[i+1];
  691.         return;
  692.       }
  693. }
  694. static void printCourseInfo(Course *somSelf)
  695. {
  696.     int i;
  697.     CourseData *somThis = CourseGetData(somSelf);
  698.     printf("  %s %s \n", _code, _title);
  699.     printf("  Instructor Name : %s \n", _instructor);
  700.     printf("  Credit = %d, Capacity = %d, Enrollment = %d \n\n",
  701.              _credit, _capacity, _enrollment);
  702.     printf("  STUDENT LIST: \n\n");
  703.     for(i=0; i<_enrollment; i++) {
  704.       _printStudentInfo(_studentList[i]);
  705.       printf("\n");
  706.     }
  707. }
  708. ((end figure 9))
  709.  
  710. Notice in particular the method printCourseInfo().  This method
  711. goes through the array studentList invoking the method
  712. printStudentInfo() on each student.  This method is defined for
  713. Student, and then overridden by both GraduateStudent and
  714. UnderGraduateStudent.  Since the array element can point to any
  715. of these three classes, we can't tell at compile time what the
  716. actual type of the target object is, only that the target object
  717. is either a Student or some type derived from Student.  Since
  718. each of these classes defines a different printStudentInfo()
  719. method, we don't know which of these methods will be invoked with
  720. each pass of the loop.  This is all under the control of override
  721. resolution.
  722.  
  723. THE SOM CLIENT
  724. Now let's see how a client might make use of these four classes
  725. in a program.  As we look at the program example shown in figure
  726. 10, we can discuss how objects are instantiated, or created, in
  727. SOM, and how methods are invoked.
  728.  
  729. ((start figure 10, caption: SOM client code))
  730. #include <student.h>
  731. #include <course.h>
  732. #include <graduate.h>
  733. #include <undgrad.h>
  734. main()
  735. {
  736.   Course *course = CourseNew();
  737.   GraduateStudent *jane = GraduateStudentNew();
  738.   UnderGraduateStudent *mark = UnderGraduateStudentNew();
  739.   _setUpCourse(course, "303", "Compilers ",
  740.      "Dr. David Johnson", 3, 15);
  741.   _setUpGraduateStudent(jane,"423538","Jane Brown",
  742.      "Code Optimization","Ph.D.");
  743.   _setUpUnderGraduateStudent(mark,"399542",
  744.      "Mark Smith", "12/17/92");
  745.   _addStudent(course, jane);
  746.   _addStudent(course, mark);
  747.   _printCourseInfo(course);
  748. }
  749. ((end figure 10))
  750.  
  751. A class is instantiated with the method classNameNew(), which is
  752. automatically defined by SOM for each recognized class.  Methods
  753. are invoked by clients just as they are inside SOM methods, and
  754. very similarly to our earlier C examples.  The first parameter is
  755. the target object.  The remaining parameters are whatever
  756. information is needed by the method.  The only odd feature is the
  757. underscore preceding the method name, which turns what looks like
  758. a regular function call into a macro defined in the .h file.
  759.  
  760. When run, the client program gives the output shown in figure 11.
  761.  
  762. ((start figure 11, caption: Client Program Output))
  763.  
  764.   303 Compilers
  765.   Instructor Name : Dr. David Johnson
  766.   Credit = 3, Capacity = 15, Enrollment = 2
  767.  
  768.   STUDENT LIST:
  769.  
  770.     Id         : 423538
  771.     Name       : Jane Brown
  772.     Type       : Graduate
  773.     Thesis     : Code Optimization
  774.     Degree     : Ph.D.
  775.  
  776.     Id         : 399542
  777.     Name       : Mark Smith
  778.     Type       : UnderGraduate
  779.     Grad Date  : 12/17/92
  780. ((end figure 11))
  781.  
  782. In the client program output we can see the override resolution
  783. at work in the different styles of displaying UnderGraduates and
  784. GraduateStudents.  A Course thinks of itself as containing an
  785. array of Students, and knows that any Student responds to a
  786. printStudentInfo() method.  But the printStudentInfo() method
  787. that a UnderGraduate responds to is different than the
  788. printStudentInfo() method that a GraduateStudent responds to, and
  789. the two methods give different outputs.
  790.  
  791. COMPARISON TO C++
  792. In this section we will compare some SOM features to those of the
  793. most widespread Object-Oriented programming language, C++,
  794. developed by Bjarne Stroustrup.  Some good introductory books
  795. about Object-Oriented programming in C++ are Class Construction
  796. in C and C++ [Sessions, 91], The C++ Programming Language
  797. [Stroustrup], and C++ Primer [Lippman].
  798.  
  799. SOM has many similarities to C++.  Both support class
  800. definitions, inheritance, and overridden methods (called virtual
  801. methods in C++).  Both support the notion of encapsulation.  But
  802. whereas C++ is designed to support standalone programming
  803. efforts, SOM is primarily focused on the support of commercial
  804. quality class libraries.  Most of the differences between SOM and
  805. C++ hinge on this issue.
  806.  
  807. C++ class libraries are version dependent, while SOM class
  808. libraries are version independent.  When a new C++ class library
  809. is released, client code has to be fully recompiled, even if the
  810. changes are unrelated to public interfaces.  This problem is
  811. discussed in detail in the book Class Construction in C and C++
  812. [Sessions, 91].  SOM, unlike C++, directly supports the
  813. development of upwardly compatible class libraries.
  814.  
  815. C++ supports programming in only one language, C++.  SOM is
  816. designed to support many languages (although in this first
  817. release it supports only C).  Rather than a language, SOM is
  818. really a system for defining, manipulating, and releasing class
  819. libraries.  SOM is used to define classes and methods, but it is
  820. left up to the implementor to choose a language for implementing
  821. methods.  Most programmers will therefore be able to use SOM
  822. quickly without having to learn a new language syntax.
  823.  
  824. C++ provides minimal support for implementation hiding, or
  825. encapsulation.  C++ class definitions, which must be released to
  826. clients, typically include declarations for the private data and
  827. methods.  This information is, at best, unnecessarily detracting,
  828. and at worst, proprietary.  In SOM, the client never has to see
  829. such implementation details.  The client need see only the .sc
  830. files, which by definition contain only public information.
  831.  
  832. C++ has limited means of method resolution.  SOM offers several
  833. alternatives.  Like C++, SOM supports offset method resolution,
  834. meaning that each method is represented by a method pointer which
  835. is set once and for all at compile time.  Unlike C++, SOM also
  836. offers facilities for resolving methods at run time.  Name Lookup
  837. resolution allows a client to ask for a pointer to a method by
  838. method name.  Dispatch resolution allows a client to package
  839. parameters at run time for dispatching to a method, a technique
  840. which allows SOM to be integrated into interpreted languages,
  841. such as Smalltalk.
  842.  
  843. One other interesting difference between SOM and C++ is in their
  844. notion of class.  In C++, the class declaration is very similar
  845. to a structure declaration.  It is a compile-time package with no
  846. characteristics that have significance at runtime.  In SOM, the
  847. class of an object is an object in its own right.  This object is
  848. itself an instantiation of another class, called the metaclass.
  849. The class object supports a host of useful methods which have no
  850. direct parallels in C++, such as somGetName(), somGetParent(),
  851. and somFindMethod().
  852.  
  853. SUMMARY
  854. A new Object Modeling System is introduced in OS/2 2.0. This
  855. object model is called The System Object Model, or SOM.  SOM is a
  856. dynamic object model which can provide useful class information
  857. about objects at run time. The goal of SOM is to support the
  858. development of class libraries useful by both compiled and
  859. interpreted languages.
  860.  
  861. ACKNOWLEDGEMENTS
  862. SOM is the work of many people.  Mike Conner developed the
  863. initial idea and implementation, and continues to lead the
  864. overall design of SOM.  Andy Martin designed the SOM Class
  865. Interface Language, and designed and implemented the class
  866. Interface compiler.  Larry Raper implemented many features of the
  867. run time library and ported SOM to OS/2.  Larry Loucks provided
  868. close technical tracking and was instrumental in focusing the
  869. effort.  Early SOM users who contributed much to the evolution of
  870. SOM include Nurcan Coskun, Hari Madduri, Roger Sessions, and John
  871. Wang.  The project is managed by Tony Dvorak.
  872.  
  873. BIBLIOGRAPHY
  874. [Lippman] Stanley B. Lippman: C++ Primer, Second Edition.
  875. Addison-Wesley, Reading, Massachusetts, 1989.
  876.  
  877. [Sessions, 89] Roger Sessions: Reusable Data Structures for C.
  878. Prentice-Hall, Englewood Cliffs, New Jersey, 1989.
  879.  
  880. [Sessions, 91] Roger Sessions: Class Construction in C and C++,
  881. Object-Oriented Programming Fundamentals. Prentice-Hall,
  882. Englewood Cliffs, New Jersey, 1991 (in press).
  883.  
  884. [SOM] Tentative Title: System Object Model Users Guide.  IBM
  885. Publication, 1991 (in preparation).
  886.  
  887. [Stroustrup] Bjarne Stroustrup: The C++ Programming Language,
  888. Second Edition.  Addison-Wesley, Reading, Massachusetts, 1991.
  889.  
  890. BIOGRAPHIES
  891. Nurcan Coskun, IBM, 11400 Burnet Road, Austin, TX 78758
  892. Nurcan Coskun has a B.S. in Industrial Engineering from Middle
  893. East Technical University, an M.S. and a Ph.D. in Computer
  894. Science from University of Missouri-Rolla.  Her expertise is in
  895. integrated programming environments, code generators, incremental
  896. compilers, interpreters, language based editors, symbolic
  897. debuggers, application frameworks, and language design.  She is
  898. now working on Object-Oriented programming environments and
  899. previously worked on the OS/2 Database Manager.  Nurcan can be
  900. contacted at nurcan@ausvm1.iinus1.ibm.com
  901.  
  902. Roger Sessions, IBM, 11400 Burnet Road, Austin, TX 78758
  903. Roger Sessions has a B.A. in Biology from Bard College and an
  904. M.E.S. in Database Systems from the University of Pennsylvania.
  905. He is the author of two books, Reusable Data Structures for C,
  906. and Class Construction in C and C++, and several articles.  He is
  907. working on Object-Oriented programming environments and
  908. previously worked with high performance relational databases and
  909. Object-Oriented storage systems.  Roger can be contacted at
  910. sessions@ausvm1.iinus1.ibm.com.
  911.  
  912.  
  913.