Unlike data fields, method names can be duplicated. This is an important feature that allows method overriding, which in turn facilitates polymorphism in the design of object-oriented programs. Method overriding allows a subclass to provide its own implementation of a method already provided by one of its superclasses. When a method is called on an object, IDL searches for a method of that class with that name. If found, the method is called. If not, the methods of any inherited object classes are examined in the order their INHERITS specifiers appear in the structure definition, and the first method found with the correct name is called. If no method of the specified name is found, an error occurs.

The method search proceeds depth first, left to right. This means that if an object’s class does not provide the method called directly, IDL searches through inherited classes by first searching the left-most included class—and all of its superclasses—before proceeding to the next inherited class to the right. If a method is defined by more than a single inherited structure definition, the first one found is used and no warning is generated. This means that class designers should pick non-generic names for their methods as well as their data fields. For example, suppose we have defined the following classes:

struct = { class1, data1}
struct = { class2, data2a:0, data2b:0.0, inherits class1 }
struct = { class3, data3:'', inherits class2, inherits class1 }
struct = { class4, data4:0L, inherits class2, inherits class3 }

Furthermore, suppose that both class1 and class3 have a method called Print defined.

Now suppose that we create an object of class4, and call the Print method:

A = OBJ_NEW('class4')
A->Print

IDL takes the following steps:

  1. Searches class4 for a Print method. It does not find one.
  2. Searches the left-most inherited class (class2) in the class definition structure for a Print method. It does not find one.
  3. Searches any superclasses of class2 for a Print method. It finds the class1 Print method and calls it on A.

Notice that IDL stops searching when it finds a method with the proper name. Thus, IDL doesn’t find the Print method that belongs to class3.

When are Methods Associated with Object Classes?


It is important to note that IDL will associate a method with objects of a given class the first time the method is called on an object of that class. This means that if a new method definition is compiled after the first time a method with a particular name is called, the new definition will not be used until a new IDL session begins.

Extending the example above, suppose that after calling the Print method you compile a new class4::Print method. Subsequent calls to the Print method will still invoke the class1::Print method even though the object instance A’s “own” Print method now exists. Once an association has been formed between an object class and a method, that association is not changed for the duration of the IDL session.

To ensure that the correct method is selected, either ensure that the method is compiled before the first time it is called or explicitly specify the class name when calling the method, as described below.

Specifying Class Names in Method Calls


If you specify a class name when calling an object method, like so:

ObjRef->classname::method

Where classname is the name of one of the object’s superclasses, IDL will search classname and any of classname’s superclasses for the method name. IDL will not search the object’s own class or any other classes the object inherits from.

This type of method call is especially useful when a class has a method that overrides a superclass method and does its job by calling the superclass method and then adding functionality. In our simple example from Calling Method Routines, we could have defined a Print method for each class, as follows:

PRO class1::Print
    PRINT, self.data1
END
PRO class2::Print
    self->class1::Print
    PRINT, self.data2a, self.data2b
END

In this case, to duplicate the behavior of the Print1 and Print2 methods, we make the following method calls:

A->Print

IDL prints:

0.00000

And now the B:

B->Print

IDL prints:

0.00000
0           0

Now we’ll use the second method:

B->class1::Print

IDL prints:

0.00000

And now A:

A->class2::Print

IDL prints:

% CLASS2 is not a superclass of object class CLASS1.
% Execution halted at:  $MAIN$