Omnis Technical Note TNOO0004 December 2007

Beginners guide to Abstraction and Inheritance

For Omnis Studio 3/4
By Andreas Pfeiffer

Many Omnis 7 developers wonder how they could best use the possibilities of inheritance in Omnis Studio. A keyword for thinking about inheritance, and for this tech note, is "Abstraction". In the context of developing applications in Omnis, abstraction and inheritance means making generic components that you can reuse many times in your application, thus making your application quicker to build, more consistent, easier to enhance and easier to fix problems.

Imagine you have got a window which displays the address and other details of an address record. In such a window, you may want to implement pushbuttons that enable the user to search, edit, insert, or delete records. However functions like this may be required in many different areas in your application like contacts, master data, and so on. Of course you could program all these functions for each window again, and again...

The alternative is to build something once, and reuse it many times; and this is where abstraction and inheritance come into play. To create a generic data window, you could create a window class which contains standard data handling buttons, while the data itself is handled using a single row variable, such as "ivDataRow", which is an instance variable of the window class. Note that this row variable is not called something like "ivAdressRow", but has an abstract name. At this point you don't know yet with which table class your row variable will connect to, therefore you can create a second instance variable of the type Item Reference, called something like "ivTableClassRef".

In the $construct() method of the window class, the reference variable points to a table class which is connected to a certain schema class. (This task will later on be taken over by the inherited window.) So you can enter the following code in the $construct:

; Overwrite this method and assign ivTableClassRef to the required one
; then do inherited
Do ivDataRow.$definefromsqlclass(ivTableClassRef)

Now you can add the buttons for Search, Edit, and so on, to the super class and program them accordingly.

window

The code to delete a record behind the Delete pushbutton could look like the following:

On evClick
 No/Yes message (Icon,Sound bell) {Do you really want
  to delete "[IvDataRow.[ivColsToBeDisplayed.c1]]"?}
 If flag true
  If ivDataRow.$delete()
   Do ivDataRow.$clear()
   Do $cinst.$redraw()
  Else
   OK message Database message (Sound bell) {The data record
   could not be deleted.//Error: [ivDataRow.$getErrorText()]}
  End If
 End If

You don't know which column name will be used for column 1 of the row variable so you can use the short form "c1" to access the first column of ivDataRow.

Keep in mind that you should program all database-specific methods in the table class itself, otherwise all other code that applies to all can be in the super class. Note also that all general functions belong in the super class and the specialisation into the inherited class.

To create a sub-class, right-click on the superclass in the Studio Browser and select "Make Subclass" in the context menu.

Make subclass

Enter a name for the new class, such as "wAddress". In this class, overwrite the $construct() method by clicking on it with the right mouse and selecting "Overwrite". Now you can set your instance variable ivTableClassRef with the command "Set Reference". Don't forget to activate your inherited code with the command "Do inherited". For example:

Set reference ivTableRef to $tables.T_Address
Do inherited

From thereon, you only need to add the fields to your new address window and assign their $dataname to a cell of the row variable "ivDataRow".

assign dataname

This way you can create your detail window with just a few steps and implement the specialisation in the inherited windows. General functions can be positioned in abstracted form in the super class. In the future, you can add new functions to the superclass and all its sub-classes will inherit the new functionality automatically.