Summary comparison of classes and procedures
- Last Updated: March 30, 2020
- 1 minute read
- OpenEdge
- Version 12.2
- Documentation
The following table compares the application implemented by the sample classes (see Sample classes) with the equivalent application implemented by comparative procedures (see Comparative procedures). The code numbers in the table match the commented numbers in the code for both classes and procedures.
| Code No. | Sample classes | Comparative procedures |
|---|---|---|
| 1 | The acme.myObjs.CustObj class
inherits from acme.myObjs.Common.CommonObj. (Note that CustObj can
reference its super class as CommonObj because
a USING statement specifies its package.) |
CustProc.p defines a handle
variable and runs CommonProc.p persistently, setting
that handle. CustProc.p then uses ADD-SUPER-PROCEDURE( ) to
define CommonProc.p as its super procedure. |
| 2 | All the setup for acme.myObjs.CustObj takes
place in its constructor. |
All the setup for CustProc.p takes
place in the main block of the procedure. |
| 3 | To establish an object reference to acme.myObjs.Common.MsgObj,
the MessageHandler( ) method is implemented and
invoked inside the acme.myObjs.CustObj class. The
method is defined as abstract in the super class (CommonObj)
and returns an instance of acme.myObjs.Common.MsgObj. |
To establish a handle to MsgProc.p, the MessageHandler user-defined
function, which returns a handle to MsgProc.p is
first defined as a prototype IN SUPER.
The function is defined in the super procedure, CommonProc.p.
It is later invoked CustProc.p and returns a handle
to MsgProc.p. |
| 4 | The updateTimestamp( ) method
is invoked on an instance of the abstract acme.myObjs.Common.CommonObj,
where it is implemented, and also inherited by acme.myObjs.CustObj.
This method is also called on a passed CommonObj reference
from InitializeDate( ), which is implemented
in the acme.myObjs.Common.HelperClass class and
called, in turn, from ObjectInfo( ) of
the Main class. |
The updateTimestamp internal
procedure is called directly from Main.p in CustProc.p,
and is found in its super procedure, CommonProc.p.
The same internal procedure is called directly from NEMain.p in NECustProc.p, and
is found in its super procedure, CommonProc.p. |
| 5 | The updateTimestamp( ) method
initializes the value of the PROTECTED dtTimestamp data
member in acme.myObjs.Common.CommonObj. Because it
is an inherited data member, it can be referenced in both the subclass, acme.myObjs.CustObj,
and its subclass, acme.myObjs.NECustObj. |
The updateTimestamp procedure
in CommonProc.p initializes the value of the SHARED variable, dtTimestamp.
In order for both CustProc.p and NECustProc.p to
use dtTimestamp, they must both define it as NEW SHARED for reference
by their own CommonProc.p super procedures. Note that
super procedures do not provide data inheritance, requiring the
use of either shared variables (as in this case) or internal procedures
and user-defined functions to encapsulate and provide access outside
the defining context. |
| 6 | When acme.myObjs.CustObj is
deleted, the destructor automatically runs and cleans up program
resources. |
Before deleting the procedure object, the internal
procedure CleanUp is called in both Main.p and NEMain.p to clean
up resources. |
| 7 | The acme.myObjs.NECustObj class
inherits from acme.myObjs.CustObj, which inherits
from acme.myObjs.Common.CommonObj, as described
in for Code No. 1. This allows the Main class to access
all of the methods on NECustObj that it accesses
on CustObj, depending on the constructor used to instantiate Main. |
NECustProc.p must go through
the same process to add CommonProc.p as a super
procedure, as did CustProc.p, as described in Code
No. 1. In addition, NECustProc.p must also add CustProc.p as
a super procedure in order for NEMain.p to access
all of the internal procedures in NECustProc.p that Main.p accesses
in CustProc.p. |
| 8 | The constructor for acme.myObjs.NECustObj invokes
the constructor for acme.myObjs.CustObj using the SUPER statement.
If the CustObj constructor took parameters, (which
it does not in this case), NECustObj would pass
them in this statement. |
If CustProc.p took parameters
(which it does not in this case), as for any calling procedure, NECustProc.p would
then have to pass them when it ran CustProc.p. |
| 9 | The acme.myObjs.NECustObj class
overrides the GetCustomerName( ) method
in acme.myObjs.CustObj. The override uses the SUPER system
reference to invoke the super class implementation of this method. |
NECustProc.p defines a separate
version of the GetCustomerName internal procedure defined
in the super procedure CustProc.p. The NECustProc.p version
uses the RUN SUPER statement to invoke the super procedure
implementation of this internal procedure. |
| 10 | The Main class defines two
(overloaded) constructors, one without parameters that initializes
an acme.myObjs.CustObj instance and one that takes,
as a parameter, the name of a text file containing E-mail addresses used
to initialize an acme.myObjs.NECustObj instance.
The driver procedure, Driver.p, instantiates the Main class once
for each constructor, followed by an associated call to the Main method, ObjectInfo( ),
which drives the reporting for the currently instantiated customer
object. Note that ObjectInfo( ) uses reflection
to identify the type name of the particular customer object currently
referenced by rCustObj. It can then display an
alert box indicating the time when it starts initializing reports
for the identified customer object. |
Main.p and NEMain.p each
implement separate procedure mainlines. Main.p instantiates
and drives the CustProc.p procedure object and NEMain.p instantiates
and drives the NECustProc.p procedure object, which takes
as a parameter the name of a text file containing E-mail addresses
used to initialize a NECustProc.p object. Because
each driver procedures knows the identity of the particular procedure
object it is instantiating, it can display a specific alert box
to indicate the initialization time of reports for that object. |
| 11 | The acme.myObjs.CustObj class
defines two overloadings of the printObj( ) method, one
that prints a single copy of a report of data for all customers
to the default printer and another that prints the number of copies
specified by a parameter. CustObj defines these
method overloadings because it implements the interface, acme.myObjs.Interfaces.IBusObj, which
specifies them. In addition, the acme.myObjs.NECustObj class
overrides this overloaded method to print a report of e-mail addresses
for New England customers in a similar manner. The main driver method, ObjectInfo( ),
defined in the Main class and called by Driver.p, determines
which overloading of printObj( ) to call
from its own input parameter. |
The CustProc.p procedure defines
a single PrintProc internal procedure that prints
one copy, or as many copies specified by a parameter, of the report
for all customers. The NECustProc.p procedure defines
its own version of PrintProc that effectively "overrides"
the version in CustProc.p to print the mail address report
for New England customers in a similar manner.The printObj( ) method
overloadings in the class samples might be more simply implemented
like PrintProc in the procedure samples. However,
the use of overloading does allow a different distribution of logic
in the same decision tree while conserving the method name. |
| 12 | The acme.myObjs.CreditObj class
defines a property, CustCreditLimit, that is readable
from outside the class hierarchy (PUBLIC), but
writable only from the defining class or its subclasses (PROTECTED).
In this case, the property is written by the CheckCustCredit( ) method
that is defined within the CreditObj class, and
is read by the CheckCredit( ) method that
is defined within the unrelated acme.myObjs.CustObj class. |
CreditProc.p defines a private CustCreditLimit variable and two user-defined functions to
access it. The GetCreditLimit function reads the
variable value and is publicly accessible. The SetCreditLimit function writes the variable value, but is only accessible
from within CreditProc.p (PRIVATE) and is called by the internal procedure, CheckCustCredit. The GetCreditLimit
function is called by the CheckCredit internal
procedure in CustProc.p. |
| 13 | The acme.myObjs.CreditObj class
provides error handling for both the CustCreditLimit property
and the CheckCustCredit( ) method. The CustCreditLimit property
throws an error object initialized with an error string when it
is set for a customer whose balance is over their current credit limit.
The CheckCustCredit( ) method automatically re-throws
the property error object, if thrown, up to its caller, and also throws
its own error object initialized with an appropriate error string
for an unavailable Customer record. The CheckCredit( ) method
in the acme.myObjs.CustObj class responds to both of
these error conditions raised by the method. |
CreditProc.p provides a similar structured
error handling capability for its corresponding user-defined functions
and internal procedure, and the CheckCredit internal
procedure of CustProc.p responds to these error conditions
in a similar manner, as well. |
| 14 | The acme.myObjs.CustObj class
defines a PROTECTED temp-table (ttCustomer)
that is accessed by its subclass, acme.myObjs.NECustObj.
Because of data inheritance, both CustObj and NECustObj directly
access the same instance of ttCustomer. |
CustProc.p defines a private temp-table (ttCustomer)
that it provides to NECustProc.p using one of its
internal procedures (GetTT), which passes the temp-table
as an OUTPUT parameter. Note that the temp-table parameter
is passed using the BIND option to a REFERENCE-ONLY definition
of ttCustomer in NECustProc.p.
This allows both CustProc.p and NECustProc.p to
access the same instance of ttCustomer. |
| 15 | Several methods in the acme.myObjs.CustObj, acme.myObjs.NECustObj,
and acme.myObjs.CreditObj classes execute FIND statements
with the NO-ERROR option. The choice is made to
use traditional error handling for these statements to show its
use together with structured error handling. |
The CustProc.p, NECustProc.p,
and CreditProc.p procedures rely on the same traditional
error handling technique to handle their FIND statement
results. |
| 16 | The public class event, OutputGenerated, is initially defined as abstract in acme.myObjs.Common.CommonObj, along with the protected
PublishOutputGenerated( ) method intended for
publishing the event. Both are implemented by the derived class, acme.myObjs.CustObj. Providing PublishOutputGenerated( ) allows not only CustObj, but the derived class, acme.myObjs.NECustObj, to publish the event in their respective versions
of the printObj( ) and logObj( ) methods, which generate the application output for each
class.The |
The sample procedures use an OutputGenerated named
event to provide similar behavior. In this case, CustProc.p and NECustProc.p each
publish the event from their respective versions of the printProc and logProc internal
procedures, which generate the application output.Each of the customer
procedure objects, CustProc.p and NECustProc.p,
is instantiated by a dedicated driver procedure, Main.p and NEMain.p (respectively),
and each driver procedure subscribes its own handler for the OutputGenerated event
published by its particular customer procedure object. |