` Printed Icetips Article

Icetips Article



OOP: Better OOP part 2
2003-04-12 -- Dan Pressnell
 
Newsgroups: comp.lang.clarion,topspeed.topic.oop

March 5, 2006:
Note that the code is now available at:

http://www.icetips.com/downloadfile.php?FileID=59

To do object oriented programming in Clarion, first you have to understand
what "objects" are in Clarion.  Clarion objects come in two flavors.  The
most common is the CLASS.  Less common, and less understood, is the
INTERFACE, which is usually nothing more than a different way of using a
class.  Concentrate on classes, first.  You have to understand classes
before you understand how to write an interface.  (You can almost always get
by with classes and forget about interfaces.)

A class can be thought of as a mini-program.  Ideally, a class contains all
the functionality and data that it needs to perform its tasks, in isolation
from the rest of your program.  This is a goal--not a rule--because in
Clarion programs classes often need to access global data, most
significantly the file declarations that are global to your program.

Given that you can think of a class as a mini-program, think about how
programs are constructed.  A program has data, a map, and procedures.  That
exactly what a class has.  Look at this class declaration:

CustomerOrderClassType    class, type
Q                                   &CustomerOrderQueueType
CustomerID                    long
GetData                          procedure()
Construct                        procedure()
Destruct                          procedure()
                                    end

CustomerOrderQueueType    queue, type
CustomerID            long
CustomerName       long
OrderID                  long
OrderDate               long
OrderAmount          decimal(20,2)
OrderBalance          decimal(20,2)
                               end

That class has two data items, Q and CustomerID.  That data belongs to the
class.  It doesn't belong to any other part of your program, in a strict
sense, although if the rest of your program has access to the class, it has
access to the class's data.

The class also has three procedures.

So the class has a data structure, and it has a collection of procedure
declarations (like a MAP).  Again, a mini-program.

With the possible exception of references to application files, the class
contains all the information it needs to function on its own, independently
of any other part of your program.  This does not mean that the class won't
use other parts of your program, or even use other classes.  It does mean
that it is designed in a way that should not interfere with other things in
your program, and it can be used from any part of your program without
changes for the specific situation.

Notice the Q that is part of the class declaration, and is a type, as
defined later.  To have a queue as class data, you have to declare a
reference to a queue type.  The queue that belongs to a specific instance of
a class will be created typcally in the Construct method for the class, and
disposed in the Destruct method.  Like this:


CustomerOrderClassType.Construct    procedure()
    code
    self.q &= new CustomerOrderQueueType

CustomerOrderClassType.Destruct      procedure()
    code
    dispose(self.q)

The Construct method will be executed automatically whenever you have a copy
of the class come into focus (is created), and the Destruct method will
execute automatically when the class goes out of focus (is destroyed).
Creating queues (and classes) with NEW in the Construct method and disposing
them in the Destruct method is a common technique in Clarion.

The GetData method would retrieve information about orders for a customer.
A possible use would be this:

cc    CustomerOrderClassType  ! declare an instance of the class
    code
    cc.CustomerID = loc:CustomerID
    cc.GetData()

At this point, the local instance of the class, "cc" would contain the data
you have requested for the CustomerID that is held in the local variable
loc:CustomerID.  You have access to the data in the class by having access
to the Q field in the class.  For example, if you wanted to show the
customer name in the first queue record, you could do this:

    get(cc.q, 1)
    message('Customer Name: ' & cc.q.CustomerName)

Notice that here, in using the class, you have not concerned yourself with
how the class does its work.  You have simply primed it with a CustomerID,
executed the method that retrieves the data, and used the data after it is
retrieved.  The complexities of retrieving the data are completely hidden
from the part of your program that uses the class for it's purpose.  (I
leave the code for the GetData method to your imagination.)

So how can this class be used?  You can use it to display the customer's
orders in a list box, print them on a report, put them into a spreadsheet,
create an HTML file, or even export them to another data format.  Assuming
your GetData method works correctly, you will always get the same
information correctly no matter how you are going to use it.

This is what is meant by reusable code.  Reusable code does not mean copy
and paste. :)

When writing reusable classes, there are some more mechanics to consider
than what I've shown here.  Those will be next.

Dan



Printed May 4, 2024, 9:02 pm
This article has been viewed/printed 35129 times.
Google search has resulted in 27 hits on this article since January 25, 2004.