Amiga E OOP Tutorial Part 3


OBJECT INHERITANCE

One of the most interesting features of OOP is the capability of creating objects based upon previously created ones, forming new more complex objs. This feature is called "inheritance", and it is a very powerful item for the coder, but it is also, under a lot of points of view, very complex to be used at best.

By designing an object you wish to inherit effectively, you'll need a very long planification session of the object itself: what you should make public and what to hide, keeping in mind that a new object will see just the public parts of the original object.


Before to continue our discussion, it is better to define a certain terminology:

CLASS: It is an object with internal vars and manipulating procs.

ROOTCLASS: The original class inherited by other objects.

SUPERCLASS: Current object's previous class, the "father" of the object.a

METHOD: An object function.

CONSTRUCTOR: Method used to initialize one object.

DESTRUCTOR: Method used to kill an object and to free all resources it has allocated.


In E, to write an object which inherits another one, you just have to write:
OBJECT obj_name OF father_obj
  def...
  def...
ENDOBJECT

All the rest is just as the creation of a single object.


WARNING: during this article, we'll show some incompleted code sections, to be considered as a demo only. Amiga E syntax, also, in creating/disposing one object will not be fully respected.
Writing an inheritable object forces to define some methos that let other objects to access inner resources and this should also be dengerous expecially if used by novice coders. Let's do a pratical example:

Suppose we have an object "image" so defined:

OBJECT image
  PRIVATE
  cols:PTR TO cmap
  bmp :PTR TO bitmap
ENDOBEJCT

and these methods:

bitmaptoscreen(scr:PTR TO screen) - Used to show bitmap on the screen.
colorstoscreen(scr:PTR TO screen) - Used to set picture's palette.

With these methods, you can actually show one image and the user of the object should never worry to know effectively where are bitmap and colormap pointers: this is a very safe method because resources allocated by the object will be freed by the object itself: so there should be no problem. But suppose we want to create an object called "remap" that allows colour remapping of an object called "image" with a different palette.

"Remapper" object has to access (and modify) "image" object's data: so we have to define these two new methods (still inside the "image" object):

bitmap() - Returns bitmap pointer.
cols()   - Returns colormap pointer.

And we will need also methods to create and dispose some object's parts:

alloc(width, height, depth) - Alloc a bitmap 
free()                      - Free a bitmap

"remapper" object should be so defined:

OBJECT remapper OF image
ENDOBJECT

remap(pal:PTR TO cmap) IS self.makeremap(SUPER self.bitmap(), SUPER self.cols(), pal)

remap() method I have just shown has some peculiarity very interesting, and it is better to discuss it now. First of all, notice the SUPER keyword which allows you to call a method inside an object previous than the current. This is needed, in our situation, because "remapper" object, inheriting all "image", has also its own "bitmap()" and "cols()" methods, that in the current object are unused pointers: with the SUPER method will be invoked the method of previous object, so you can effectively access to desired data (in our case, palette and bitmap pointers of "image").


OBJECT REDEFINITION OF METHODS

Another feature of objects inheriting a previous one, is that they can redefine previous object's methods. Redefinition is a very powerful tool that allows to "similar" objects to behave differently. This feature, used with the SUPER command allows simplifications and enhancements of objects... or just to enhance our code.

Returning to our example, we could redefine bitmap() and cols() method in "remapper" object in this way:

bitmap() OF remapper IS SUPER self.bitmap() - Call "image" 's bitmap()
cols() OF remapper IS SUPER self.cols()  - Call "image" 's cols()

And so we could define remap() in this way:

remap IS self.makeremap(self.bitmap(), self.cols(), pal)
Naturally, this is quite an unuseful example and it is not very meaningful, but we'll do more interesting one later.

SUMMARY

Now we'll have a fast review of what has been exposed in this issue, because it is very important for a correct (and valuable) use of objects and their programming.

INHERITANCE: an object can inherit another one and use all its features. In Amiga E, the syntax is the following:

OBJECT new_obj OF old_obj
  newobj definition
ENDOBEJCT

METHODS REDEFINITIONS: an object created upon another, can redefine its methods and behaves in a completely safe way.

In Amiga E, the syntax is the following:

PROC method_name() OF new_obj
  new code
	....
  new code
ENDPROC

SUPER: it is a particular interesting command because it offers the opportunity of invoking an original object's method from the new object.

In Amiga E, the syntax is the following:

SUPER self.method()  -> call method() of old_obj.

EXAMPLE This month we have decided to divide the real source code from the rest of the article so we allows a better loading speed.

To have a working example press here.

Good source studying!!


Main Page


    Written By: Fabio Rotondo      e-mail: fsoft@intercom.it
                C.so Vercelli 9
                28100 Novara
                ITALY               tel:    (ITA) - (0)321 459676