Jump to content

Object-Oriented Programming Using SOM and DSOM/Understanding the Basics

From EDM2
Revision as of 00:18, 31 May 2018 by Ak120 (talk | contribs)

We covered the development and use of a SOM object in the last chapter. In this chapter, we will look at the SOM kernel. We will discuss the concepts and the terminologies that make up the SOM run-time environment. We will examine the SOM inheritance model and the options it provides for method resolution. A good understanding of these fundamental concepts will help you when you write your SOM programs.

SOMObject, The Root Of All SOM Classes

In SOM, an object is a run-time entity with a specific set of instance methods and instance variables. The methods can be called by a client program, and the variables store data that is specific to the object. This model is similar to most objectoriented languages.

SOMObject is the root class for all SOM classes. All SOM classes must be subclasses of SOMObject or of some other class derived from SOMObject. SOMObject introduces a number of methods that define the behavior common to all SOM objects. SOMObject has no instance variables. Therefore, inheriting from SOMObject does not increase the size of the objects.

SOMObject provides the somInit and the somUninit methods. The somInit method is called on every object as it is created in order to initialize the object. The somUninit method performs the inverse of somInit. These methods are typically overridden by subclasses that have instance variables, so they can be initialized and uninitialized.

SOMObject also provides a number of methods for obtaining information about an object at run-time. For example, you can use these methods to find the class name of an object, the size of an object or determine whether an object is an instance of a specific class. We will see a usage example in Section 4.4 on page 85.

SOMObject also provides methods for performing dispatch-function resolution, a topic that will be discussed later in this chapter.

SOMClass, The Root of all SOM Metaclasses

A SOM class defines the implementation of a SOM object. Every SOM object is an instance of a SOM class. In contrast to object-oriented languages such as C++, SOM classes are also represented as objects at run-time. Classes can have their own variables and methods. These objects are called class objects. Their variables are called class variables (to distinguish them from instance variables), and their methods are called class methods (to distinguish them from instance methods).

Just like an object is an instance of a class, a class object is an instance of another class, called a metaclass.

A class defines instance methods to which its objects respond. A metaclass defines class methods to which a class object responds. Class methods perform class-related operations such as creating new instances of a class, maintaining a count of the number of instances of the class, and other operations of a supervisory nature.

SOMClass is the root class for all SOM metaclasses. All SOM metaclasses must be subclasses of SOMClass or of some other class derived from SOMClass. SOMClass introduces a number of methods that define the behavior common to all SOM class objects. The default metaclass for every class is SOMClass.

SOMClass provides the somNew method for creating a new instance of a class. When you invoke <className>New() in C or new <className> in C++ to create an instance of <className>, the bindings invoke somNew on the specified class. The somNew method allocates space for the new class object. It then calls somInit to initialize the newly created object and returns a pointer to it.

SOMClass also provides a number of methods for obtaining information about a class at run-time. For example, you can use these methods to find the methods the class supports, its relationships with other classes, or its version number. As we will see later in this book, SOM's implementation of classes as objects gives us a lot of flexibility at run-time.

SOM Kernel Classes

The SOM kernel is made up of three classes: SOMObject, SOMClass, and SOMClassMgr. The relationship of these classes are shown in Figure 3.1.

SOMClassMgr is a special class, one instance of this class is created automatically during SOM initialization. This instance is pointed to by the global variable SOMClassMgrObject.

It maintains a run-time registry for all existing classes within the current process and assists in the dynamic loading and unloading of class libraries.

You can package multiple classes into a class library. On OS/2, these libraries are known as Dynamic Linked Libraries (DLLs). SOMClassMgr automatically loads the DLLs when you instantiate an object of a class using the language bindings. SOMClassMgr also provides methods that let you dynamically load a class if you do not know at compile time which class you are going to use. This topic is discussed in Section 4.3 on page 82.

SOMClassMgr, however, does not automatically unload a DLL when all the instances of a class are freed. It does provide methods that allow you to unload a class and its class library. However, you have to determine when it will be safe to unload a class. A technique you can use is a metaclass to keep track of all the instances that are created for a class and unload the class when they are all freed. Usage examples for a metaclass are provided later on in this chapter.

SOM Run-time Environment Initialization

During the initialization of the SOM run-time environment, four primitive SOM objects are automatically created. They are the class objects for SOMObject, SOMClass, and SOMClassMgr, plus one instance of SOMClassMgr pointed to by the global variable SOMClassMgrObject. In addition to creating these four primitive SOM objects, the initialization also sets up global variables to hold data structures that maintain the state of the environment.

So when does the initialization of the SOM run-time take place? If you are using the C or C++ bindings, the SOM run-time environment is automatically initialized the first time you create an object.

If you are using other languages, or no bindings, you need to call the som.EnvironmentNew function to initialize the SOM run-time environment.

Attributes vs. Instance Variables

In Section 2.4.3 on page 17, we specified that an attribute is an instance variable where the get and set methods are automatically generated. In SOM IDL, there is another way of defining an instance variable. One can define an instance variable in the implementation section. The syntax is identical to the ANSI C syntax for variable declarations. For example, the following declares two instance variables, x and y:

#ifdef _SOMIDL_

implementation
{
   short x;
   double y;
};
#end if

Instance variables differ from attributes in the following ways.

  1. An instance variable cannot be accessed by client programs.
  2. An instance variable cannot be accessed by subclasses' methods.
  3. An instance variable can only be accessed by the methods in the defining class.

Within the class that defines the instance variable, the way to access it is the same as an attribute. For example, to access the instance variable x, one can use the following form:

 somThis->x;         //C++ Bindings

If you want the instance data to be accessed by client programs or subclasses, use an attribute declaration instead. How to access a parent's attribute is discussed later in this chapter.

Public vs. Private

By definition, everything specified in a CORBA IDL file is public. That is, an IDL describes the services that an object provides and can be invoked by a client.

What if you want to designate some methods or data as private? In SOM IDL, you can use the #ifdef _PRNATE_ pre-processor macro. For example, the following IDL (Figure 3.2) shows how you can specify a private method.

 #include <somobj.idl>
 interface Foo : SOMObject
 {
   attribute short count;

   #ifdef _PRIVATE_
      void meth1();
   #end if

   void meth2();

   #ifdef _SOMIDL_
   implementation
   {
        releaseorder: _get_count,
                      _set_count.

 #ifdef _PRIVATE_
                      meth1,
 #else 
                      dummy
 #end if

                      meth2;

    };
    #end if

 };

Figure 3.2 Declaring a private method in IDL

When you run the SOM compiler to generate the binding files and the implementation template, you need to specify the -p option if you want the compiler to generate bindings for both the private and public attributes and methods. For example, the following command will generate a C++ implementation template that provides a stub procedure for every method in the Foo interface.

sc -p -sxc foo.idl

How do you prevent a client from knowing about the private methods? You can either generate a usage binding :file that does not contain private information by not specifying the -p option in the SOM compile command, or you can strip away the private information from the IDL file by running a utility (called pdl) that is provided with the SOM Toolkit. You then give the version that only contains public definitions to the client.

Private methods also need to be listed in the releaseorder in order to maintain binary compatibility. To prevent client from knowing the name of a private method, you can use a dummy name as a place holder in the releaseorder as il1ustrated in the above example.