Presentation is loading. Please wait.

Presentation is loading. Please wait.

DEV-20: Using Classes and Procedures in OpenEdge® 10.1B

Similar presentations


Presentation on theme: "DEV-20: Using Classes and Procedures in OpenEdge® 10.1B"— Presentation transcript:

1 DEV-20: Using Classes and Procedures in OpenEdge® 10.1B
Introducing Object-Oriented code into your Application Phillip Magnay Technical Architect

2 Goals of this Session Classes and procedures are not so different
What are the take-aways? Classes and procedures are not so different However there are key distinctions and benefits Classes and procedures can work together You can keep all of your existing procedures And start developing using classes today DEV-20: Using Classes and Procedures in OpenEdge 10.1B

3 Agenda Classes & Procedures Strong Typing
What we’re going to cover… Classes & Procedures Strong Typing Data Members, Properties & Methods Constructors & Destructors Instantiation & Destruction Mixing Procedures and Classes Together Error Handling Global Variables DEV-20: Using Classes and Procedures in OpenEdge 10.1B

4 Classes & Procedures Procedure Class /* Golfer.p */ CLASS Golfer:
DEF VAR numRounds AS INT NO-UNDO. /* Main block code */ RUN teeOff. PROCEDURE teeoff: END PROCEDURE. ON CLOSE OF THIS-PROCEDURE DO: END. CLASS Golfer: DEF PUBLIC PROPERTY numRounds AS INT NO-UNDO GET . SET . CONSTRUCTOR PUBLIC Golfer(): teeOff(). END CONSTRUCTOR. METHOD PUBLIC VOID teeOff(): END METHOD. DESTRUCTOR PUBLIC Golfer(): END DESTRUCTOR. END CLASS. DEV-20: Using Classes and Procedures in OpenEdge 10.1B

5 Class & Procedure Definitions
/* Golfer.p */ CLASS Golfer: END CLASS. .p file extension No code necessary Weak type Late-binding at run-time -p startup parameter Directly accessible across AppServer boundary .cls file extension CLASS keyword Strong type Compile-time type checking No –p startup parameter NOT directly accessible across AppServer boundary DEV-20: Using Classes and Procedures in OpenEdge 10.1B

6 Strong Typing Class as a data type
Class type references checked at compile-time Also includes checking of: Data members Properties Methods Eliminates type errors at run-time which are common using procedures DEV-20: Using Classes and Procedures in OpenEdge 10.1B

7 Every instance of Class Customer has TeeOff method (contract)
Strong Typing Procedure Class /* Golfer.p */ PROCEDURE TeeOff: DEF INPUT PARAMETER teeTime AS DATETIME NO-UNDO. END PROCEDURE. CLASS Golfer: METHOD PUBLIC VOID TeeOff (INPUT teeTime AS DATETIME): END METHOD. END CLASS. Every instance of Class Customer has TeeOff method (contract) TeeOff exists in this Persistent Procedure but not all Persistent Procedures DEV-20: Using Classes and Procedures in OpenEdge 10.1B

8 Runtime Type Checking Do you have procedural code like this?
Is this a persistent procedure? PROCEDURE InternalA: DEFINE INPUT PARAMETER pHn AS HANDLE NO-UNDO. IF pHn:TYPE = "PROCEDURE" AND CAN-DO(phn:INTERNAL-ENTRIES,"TeeOff") THEN DO: RUN TeeOff IN pHn. END. ELSE /* handle the error */ END PROCEDURE. Does it have an internal procedure called “TeeOff”? Now we can run it DEV-20: Using Classes and Procedures in OpenEdge 10.1B

9 Compile-Time Type Checking
In OO it looks like this: METHOD PUBLIC VOID InternalA (INPUT a AS Golfer): DEF VAR teeTime AS DATETIME NO-UNDO. a:TeeOff(teeTime). END. Less Code No runtime checking No runtime errors Automatically checked all 3 conditions at compile time. Just run the thing! DEV-20: Using Classes and Procedures in OpenEdge 10.1B

10 Data Members Procedure /* Golfer.p */
DEF VAR averageScore AS DECIMAL NO-UNDO. DEF TEMP-TABLE ttCourses NO-UNDO FIELD CourseName AS CHAR FIELD ParIndex AS DECIMAL FIELD Slope AS INTEGER. DEF VAR errMessage AS CHAR NO-UNDO. ABL supports data members in classes in a similar way to the data elements that you define in the main block of a persistent procedure. However, data elements in a procedure are always private, unless they are specified as SHARED, in which case they can be shared among different external procedures (persistent or non-persistent). ABL does not allow shared variables to be directly accessed by classes. The variables and other data elements defined in the main block of an external procedure are private without having an explicit access mode. That is, they are scoped to the procedure, including its internal procedures and user-defined functions, but cannot be accessed directly from other external procedures. In the same way, data members defined in a class with no access mode are PRIVATE and accessible from all methods defined in the class, but they cannot be accessed directly from other classes, whether inside or outside of the class hierarchy. USING acme.myObjs.*. CLASS acme.myObjs.NECustObj INHERITS CustObj: METHOD PRIVATE VOID DisplayCust ( ): iNumCusts = iNumCusts + 1. FOR EACH ttCust: DISPLAY ttCust. END. END METHOD. END CLASS. CLASS MyMain: DEFINE PRIVATE VARIABLE rNECust AS CLASS NECustObj NO-UNDO. rNECust = NEW NECustObj( ). rNECust:iNumCusts = rNECust:iNumCusts + 1. /* Can not access PROTECTED ttCust */ DELETE OBJECT rNECust. rNECust = ?. Using the CLASS construct 2–19 Procedures can define SHARED variables, which are scoped to and accessible from other external procedures. The variable definitions must be defined as NEW SHARED in a parent procedure and the definitions repeated as SHARED in each called external procedure that needs to access them. This is necessary because the compiler does not look at other external procedures when compiling a procedure. Classes do not support SHARED variables, which must be defined both for where they are stored and for where they are referenced. PROTECTED and PUBLIC data members in classes provide wider access to class data members and without the need to repeat the data member definitions. However, they must be referenced with respect to the instantiated object where they are defined. So, PROTECTED data members can only be referenced within the same class hierarchy of a single instantiated object where they are defined; and PUBLIC data members can be referenced like PROTECTED data members, within the class hierarchy, and also from outside the class hierarchy. However, PUBLIC data members can only be referenced outside the class hierarchy where they are defined by using an object reference to the instantiated class that defines them. These referential restrictions both conform to class and object relationships and allow the compiler to validate data member references for consistency based on these relationships. DEV-20: Using Classes and Procedures in OpenEdge 10.1B

11 Data Members Class CLASS Golfer:
DEF PUBLIC VAR averageScore AS DEC NO-UNDO. DEF PROTECTED TEMP-TABLE ttCourses NO-UNDO FIELD CourseName AS CHAR FIELD ParIndex AS DECIMAL FIELD Slope AS INTEGER. DEF PRIVATE VAR errMessage AS CHAR NO-UNDO. END CLASS. ABL supports data members in classes in a similar way to the data elements that you define in the main block of a persistent procedure. However, data elements in a procedure are always private, unless they are specified as SHARED, in which case they can be shared among different external procedures (persistent or non-persistent). ABL does not allow shared variables to be directly accessed by classes. The variables and other data elements defined in the main block of an external procedure are private without having an explicit access mode. That is, they are scoped to the procedure, including its internal procedures and user-defined functions, but cannot be accessed directly from other external procedures. In the same way, data members defined in a class with no access mode are PRIVATE and accessible from all methods defined in the class, but they cannot be accessed directly from other classes, whether inside or outside of the class hierarchy. USING acme.myObjs.*. CLASS acme.myObjs.NECustObj INHERITS CustObj: METHOD PRIVATE VOID DisplayCust ( ): iNumCusts = iNumCusts + 1. FOR EACH ttCust: DISPLAY ttCust. END. END METHOD. END CLASS. CLASS MyMain: DEFINE PRIVATE VARIABLE rNECust AS CLASS NECustObj NO-UNDO. rNECust = NEW NECustObj( ). rNECust:iNumCusts = rNECust:iNumCusts + 1. /* Can not access PROTECTED ttCust */ DELETE OBJECT rNECust. rNECust = ?. Using the CLASS construct 2–19 Procedures can define SHARED variables, which are scoped to and accessible from other external procedures. The variable definitions must be defined as NEW SHARED in a parent procedure and the definitions repeated as SHARED in each called external procedure that needs to access them. This is necessary because the compiler does not look at other external procedures when compiling a procedure. Classes do not support SHARED variables, which must be defined both for where they are stored and for where they are referenced. PROTECTED and PUBLIC data members in classes provide wider access to class data members and without the need to repeat the data member definitions. However, they must be referenced with respect to the instantiated object where they are defined. So, PROTECTED data members can only be referenced within the same class hierarchy of a single instantiated object where they are defined; and PUBLIC data members can be referenced like PROTECTED data members, within the class hierarchy, and also from outside the class hierarchy. However, PUBLIC data members can only be referenced outside the class hierarchy where they are defined by using an object reference to the instantiated class that defines them. These referential restrictions both conform to class and object relationships and allow the compiler to validate data member references for consistency based on these relationships. DEV-20: Using Classes and Procedures in OpenEdge 10.1B

12 Data Members Variables, buffers, streams, GUI objects, buffers, queries, temp-tables, ProDataSets, data sources, work tables Access Modifiers PRIVATE (Default for Data Members) PROTECTED PUBLIC Temp-Tables & ProDataSets must be defined at Class level (similar to procedures) ABL supports data members in classes in a similar way to the data elements that you define in the main block of a persistent procedure. However, data elements in a procedure are always private, unless they are specified as SHARED, in which case they can be shared among different external procedures (persistent or non-persistent). ABL does not allow shared variables to be directly accessed by classes. The variables and other data elements defined in the main block of an external procedure are private without having an explicit access mode. That is, they are scoped to the procedure, including its internal procedures and user-defined functions, but cannot be accessed directly from other external procedures. In the same way, data members defined in a class with no access mode are PRIVATE and accessible from all methods defined in the class, but they cannot be accessed directly from other classes, whether inside or outside of the class hierarchy. USING acme.myObjs.*. CLASS acme.myObjs.NECustObj INHERITS CustObj: METHOD PRIVATE VOID DisplayCust ( ): iNumCusts = iNumCusts + 1. FOR EACH ttCust: DISPLAY ttCust. END. END METHOD. END CLASS. CLASS MyMain: DEFINE PRIVATE VARIABLE rNECust AS CLASS NECustObj NO-UNDO. rNECust = NEW NECustObj( ). rNECust:iNumCusts = rNECust:iNumCusts + 1. /* Can not access PROTECTED ttCust */ DELETE OBJECT rNECust. rNECust = ?. Using the CLASS construct 2–19 Procedures can define SHARED variables, which are scoped to and accessible from other external procedures. The variable definitions must be defined as NEW SHARED in a parent procedure and the definitions repeated as SHARED in each called external procedure that needs to access them. This is necessary because the compiler does not look at other external procedures when compiling a procedure. Classes do not support SHARED variables, which must be defined both for where they are stored and for where they are referenced. PROTECTED and PUBLIC data members in classes provide wider access to class data members and without the need to repeat the data member definitions. However, they must be referenced with respect to the instantiated object where they are defined. So, PROTECTED data members can only be referenced within the same class hierarchy of a single instantiated object where they are defined; and PUBLIC data members can be referenced like PROTECTED data members, within the class hierarchy, and also from outside the class hierarchy. However, PUBLIC data members can only be referenced outside the class hierarchy where they are defined by using an object reference to the instantiated class that defines them. These referential restrictions both conform to class and object relationships and allow the compiler to validate data member references for consistency based on these relationships. DEV-20: Using Classes and Procedures in OpenEdge 10.1B

13 Properties Procedure /* Golfer.p */ DEF VAR numClubs AS INT NO-UNDO.
FUNCTION getNumClubs RETURNS INTEGER: RETURN numClubs. END FUNCTION. FUNCTION setNumClubs RETURNS LOGICAL (INPUT newNumClubs AS INTEGER): IF newNumClubs > 14 THEN RETURN FALSE. numClubs = newNumClubs. RETURN TRUE. Persistent procedures have no direct equivalent to properties of a class. You can simulate the function of properties in a persistent procedure by defining user-defined functions, each of which encapsulates access to a corresponding variable defined in the main block. In procedures, the closest equivalent to a property is a user-defined function. You might define one function equivalent to the GET accessor that returns a value, and another function (or internal procedure) equivalent to the SET accessor that accepts the setting value as an INPUT parameter. DEV-20: Using Classes and Procedures in OpenEdge 10.1B

14 Properties Class CLASS Golfer:
DEFINE PUBLIC PROPERTY numClubs AS INT NO-UNDO GET . SET (INPUT NewNumClubs AS INTEGER): IF newNumClubs > 14 THEN RETURN ERROR "Too many clubs". ELSE numClubs = newNumClubs. END SET. END CLASS. Persistent procedures have no direct equivalent to properties of a class. You can simulate the function of properties in a persistent procedure by defining user-defined functions, each of which encapsulates access to a corresponding variable defined in the main block. In procedures, the closest equivalent to a property is a user-defined function. You might define one function equivalent to the GET accessor that returns a value, and another function (or internal procedure) equivalent to the SET accessor that accepts the setting value as an INPUT parameter. DEV-20: Using Classes and Procedures in OpenEdge 10.1B

15 Methods Procedure /* Golfer.p */ … PROCEDURE AddNewScore:
DEF INPUT PARAM newScore AS INT NO-UNDO. END PROCEDURE. FUNCTION RecalcAverage RETURNS DECIMAL PRIVATE (INPUT newScore AS INTEGER): END FUNCTION. Methods generally combine the characteristics of internal procedures and user-defined functions, and add features unique to classes. Also, unlike user-defined functions, methods can raise the ERROR condition. You cannot use any statements or ABL elements in the method-body that are only relevant in procedures, such as a reference to the THIS-PROCEDURE system handle. DEV-20: Using Classes and Procedures in OpenEdge 10.1B

16 Methods Class CLASS Golfer: … METHOD PUBLIC VOID addNewScore
(INPUT newScore AS INTEGER): END METHOD. METHOD PRIVATE DECIMAL recalcAverage END CLASS. Methods generally combine the characteristics of internal procedures and user-defined functions, and add features unique to classes. Also, unlike user-defined functions, methods can raise the ERROR condition. You cannot use any statements or ABL elements in the method-body that are only relevant in procedures, such as a reference to the THIS-PROCEDURE system handle. DEV-20: Using Classes and Procedures in OpenEdge 10.1B

17 Methods Methods combine characteristics of internal procedures and user-defined functions Access Modifiers PRIVATE PROTECTED PUBLIC (Default for Members) Methods can raise ERROR condition Methods with a return type cannot block for input Methods can be overloaded Methods generally combine the characteristics of internal procedures and user-defined functions, and add features unique to classes. Also, unlike user-defined functions, methods can raise the ERROR condition. You cannot use any statements or ABL elements in the method-body that are only relevant in procedures, such as a reference to the THIS-PROCEDURE system handle. DEV-20: Using Classes and Procedures in OpenEdge 10.1B

18 Constructors Procedure /* Golfer.p */
DEF VAR currentHole AS INTEGER NO-UNDO. /* Main block code */ RUN initializeRound. PROCEDURE initializeRound. currentHole = 1. END PROCEDURE. For persistent procedures, the equivalent behavior executes directly in the main block, and there are no restrictions on where and when a particular persistent procedure can be instantiated. A constructor for a class is similar to the main block of a persistent procedure. Parameters passed to a class's constructor are similar to parameters passed to a persistent procedure when it is run. When you instantiate a class using the NEW phrase, the specified constructor executes as part of the class constructor hierarchy and returns to the caller assigning the object reference to the instantiated class. The caller can then use this object reference to access public data members and properties and to call public methods on this class-based object. When a procedure is first run PERSISTENT, the code in its main block executes and returns to the caller, setting the procedure object handle. The caller can then access any variables that it shares globally with the procedure object and can use the procedure object handle to run internal procedures and user-defined functions in the procedure object. The syntax for the SUPER statement appears similar to the syntax for the SUPER built-in function, used to invoke user-defined functions in a super procedure. However, unlike the SUPER built-in function, which you must invoke inside an expression in a procedure, you can only invoke the SUPER statement as the first statement in a subclass constructor. DEV-20: Using Classes and Procedures in OpenEdge 10.1B

19 Constructors Class CLASS Golfer:
DEF PUBLIC VAR currentHole AS INT NO-UNDO. CONSTRUCTOR PUBLIC Golfer (): initializeRound(). END CONSTRUCTOR. METHOD PUBLIC VOID initializeRound(): currentHole = 1. END METHOD. END CLASS. For persistent procedures, the equivalent behavior executes directly in the main block, and there are no restrictions on where and when a particular persistent procedure can be instantiated. A constructor for a class is similar to the main block of a persistent procedure. Parameters passed to a class's constructor are similar to parameters passed to a persistent procedure when it is run. When you instantiate a class using the NEW phrase, the specified constructor executes as part of the class constructor hierarchy and returns to the caller assigning the object reference to the instantiated class. The caller can then use this object reference to access public data members and properties and to call public methods on this class-based object. When a procedure is first run PERSISTENT, the code in its main block executes and returns to the caller, setting the procedure object handle. The caller can then access any variables that it shares globally with the procedure object and can use the procedure object handle to run internal procedures and user-defined functions in the procedure object. The syntax for the SUPER statement appears similar to the syntax for the SUPER built-in function, used to invoke user-defined functions in a super procedure. However, unlike the SUPER built-in function, which you must invoke inside an expression in a procedure, you can only invoke the SUPER statement as the first statement in a subclass constructor. DEV-20: Using Classes and Procedures in OpenEdge 10.1B

20 Constructors Constructor equates to Main Block in procedure
Constructor parameters equates to procedure parameters Constructor name must be same as Class Cannot have a return type If not explicitly defined, default constructor with no parameters is provided. Constructors can be overloaded For persistent procedures, the equivalent behavior executes directly in the main block, and there are no restrictions on where and when a particular persistent procedure can be instantiated. A constructor for a class is similar to the main block of a persistent procedure. Parameters passed to a class's constructor are similar to parameters passed to a persistent procedure when it is run. When you instantiate a class using the NEW phrase, the specified constructor executes as part of the class constructor hierarchy and returns to the caller assigning the object reference to the instantiated class. The caller can then use this object reference to access public data members and properties and to call public methods on this class-based object. When a procedure is first run PERSISTENT, the code in its main block executes and returns to the caller, setting the procedure object handle. The caller can then access any variables that it shares globally with the procedure object and can use the procedure object handle to run internal procedures and user-defined functions in the procedure object. The syntax for the SUPER statement appears similar to the syntax for the SUPER built-in function, used to invoke user-defined functions in a super procedure. However, unlike the SUPER built-in function, which you must invoke inside an expression in a procedure, you can only invoke the SUPER statement as the first statement in a subclass constructor. DEV-20: Using Classes and Procedures in OpenEdge 10.1B

21 Constructors Access Modifiers
PRIVATE PROTECTED PUBLIC (Default for constructors) PRIVATE constructors can only be invoked by another constructor defined in the Class PROTECTED constructors can only be invoked by another constructor defined in the Class or a subclass DEV-20: Using Classes and Procedures in OpenEdge 10.1B

22 Destructors Procedure /* Golfer.p */
DEF VAR scoreXLS AS COM-HANDLE NO-UNDO. ON CLOSE OF THIS-PROCEDURE DO: RELEASE OBJECT scoreXLS. END. Persistent procedures have no equivalent for a destructor. With persistent procedures, the application must adhere to an enforced programming strategy in order to allow cleanup when the procedure exits. Typically, you do this by defining a trigger block to be executed ON CLOSE OF THIS-PROCEDURE, then take care to always delete a persistent procedure instance using the APPLY "CLOSE" statement rather than using the DELETE OBJECT statement. (This is the convention used in procedures generated by the AppBuilder.) A destructor provides a uniform mechanism to handle such cleanup tasks in class-based objects without the need for special programming strategies. DEV-20: Using Classes and Procedures in OpenEdge 10.1B

23 Destructors Class CLASS Golfer: … DESTRUCTOR PUBLIC Golfer():
DEF VAR scoreXLS AS COM-HANDLE NO-UNDO. DESTRUCTOR PUBLIC Golfer(): RELEASE OBJECT scoreXLS. END DESTRUCTOR. END CLASS. Persistent procedures have no equivalent for a destructor. With persistent procedures, the application must adhere to an enforced programming strategy in order to allow cleanup when the procedure exits. Typically, you do this by defining a trigger block to be executed ON CLOSE OF THIS-PROCEDURE, then take care to always delete a persistent procedure instance using the APPLY "CLOSE" statement rather than using the DELETE OBJECT statement. (This is the convention used in procedures generated by the AppBuilder.) A destructor provides a uniform mechanism to handle such cleanup tasks in class-based objects without the need for special programming strategies. DEV-20: Using Classes and Procedures in OpenEdge 10.1B

24 Destructors Uniform mechanism to handle cleanup tasks
No real equivalent in procedures Analogous to ON CLOSE OF THIS PROCEDURE Caution: Not automatically run when client session ends Runs on explicit deletion on DELETE OBJECT Persistent procedures have no equivalent for a destructor. With persistent procedures, the application must adhere to an enforced programming strategy in order to allow cleanup when the procedure exits. Typically, you do this by defining a trigger block to be executed ON CLOSE OF THIS-PROCEDURE, then take care to always delete a persistent procedure instance using the APPLY "CLOSE" statement rather than using the DELETE OBJECT statement. (This is the convention used in procedures generated by the AppBuilder.) A destructor provides a uniform mechanism to handle such cleanup tasks in class-based objects without the need for special programming strategies. DEV-20: Using Classes and Procedures in OpenEdge 10.1B

25 Instantiation Procedure /* ProShop.p */ /* Golfer.p */ DEF VAR hGolfer
AS HANDLE NO-UNDO. /* Main block code */ RUN Golfer.p PERSISTENT SET hGolfer. /* Golfer.p */ DEF VAR scoreXLS AS COM-HANDLE NO-UNDO. /* Main block code */ RUN initialize. PROCEDURE initialize: CREATE “Excel.Worksheet" scoreXLS. END PROCEDURE. Using theAssignment (=)statement with the NEW phrase to instantiate a class and assign its object reference is roughly equivalent to running a persistent procedure and setting its procedure object handle using the RUN statement. Just as a procedure-based ABL application that instantiates persistent procedures must begin with a startup procedure file that directly or indirectly (through other procedure files) creates procedure objects, a class-based ABL application must also begin with a startup procedure file that directly or indirectly creates class-based objects. (You cannot directly startup an application with ABL using a class file as you can, for example, with Java.) When it is no longer needed, you can use the DELETE OBJECT statement to destroy either a persistent procedure or an instance of a class VALID-OBJECT function THIS-OBJECT Statement THIS-OBJECT reference DEV-20: Using Classes and Procedures in OpenEdge 10.1B

26 Instantiation Class CLASS ProShop: CLASS Golfer:
DEF PRIVATE VAR rGolfer AS CLASS Golfer NO-UNDO. CONSTRUCTOR PUBLIC ProShop(): rGolfer = NEW Golfer(). END CONSTRUCTOR. END CLASS. CLASS Golfer: DEF PRIVATE VAR scoreXLS AS COM-HANDLE NO-UNDO. CONSTRUCTOR PUBLIC Golfer(): initialize(). END CONSTRUCTOR. METHOD VOID initialize(): CREATE “Excel.Worksheet" scoreXLS. END METHOD. END CLASS. Using theAssignment (=)statement with the NEW phrase to instantiate a class and assign its object reference is roughly equivalent to running a persistent procedure and setting its procedure object handle using the RUN statement. Just as a procedure-based ABL application that instantiates persistent procedures must begin with a startup procedure file that directly or indirectly (through other procedure files) creates procedure objects, a class-based ABL application must also begin with a startup procedure file that directly or indirectly creates class-based objects. (You cannot directly startup an application with ABL using a class file as you can, for example, with Java.) When it is no longer needed, you can use the DELETE OBJECT statement to destroy either a persistent procedure or an instance of a class VALID-OBJECT function THIS-OBJECT Statement THIS-OBJECT reference DEV-20: Using Classes and Procedures in OpenEdge 10.1B

27 Instantiation NEW statement analogous to
RUN proc PERSISTENT SET handle VALID-OBJECT function analogous to VALID-HANDLE Class instance reference has a type TYPE-OF function Persistent procedure handle has no type Using theAssignment (=)statement with the NEW phrase to instantiate a class and assign its object reference is roughly equivalent to running a persistent procedure and setting its procedure object handle using the RUN statement. Just as a procedure-based ABL application that instantiates persistent procedures must begin with a startup procedure file that directly or indirectly (through other procedure files) creates procedure objects, a class-based ABL application must also begin with a startup procedure file that directly or indirectly creates class-based objects. (You cannot directly startup an application with ABL using a class file as you can, for example, with Java.) When it is no longer needed, you can use the DELETE OBJECT statement to destroy either a persistent procedure or an instance of a class VALID-OBJECT function THIS-OBJECT Statement THIS-OBJECT reference DEV-20: Using Classes and Procedures in OpenEdge 10.1B

28 Invoking Methods Procedure /* ProShop.p */ /* Golfer.p */
DEF VAR hGolfer AS HANDLE NO-UNDO. /* Main block code */ RUN Golfer.p PERSISTENT SET hGolfer. RUN addScore IN hGolfer (INPUT score). /* Golfer.p */ DEF VAR numRounds AS INTEGER NO-UNDO. /* Main block code */ PROCEDURE AddScore: DEF INPUT PARAM newScore AS INT NO-UNDO. END PROCEDURE. When you invoke an internal procedure from within an external procedure where it is defined, you use a RUN statement that simply names the procedure. When you invoke a user-defined function within an external procedure where it is defined, you name the function in an expression, similar to invoking a method within a class. However, you have to forward reference the definition for the user-defined function if it occurs after the point of invocation. When you invoke an internal procedure defined in another external procedure, you use the RUN statement with an IN option to specify the location of the internal procedure definition. When you invoke a user-defined function defined in another external procedure, you must specify the prototype and reference the location of the function definition, then invoke the function by naming it in an expression. Method invocation within its defining class or on an another object instance is far more consistent than for internal procedures and user-defined functions. Methods never require a separately declared prototype in the class where they are invoked, as user-defined functions sometimes do in the procedure or class where they are invoked. DEV-20: Using Classes and Procedures in OpenEdge 10.1B

29 Invoking Methods Class CLASS ProShop: DEF PRIVATE VAR rGolfer
AS CLASS Golfer NO-UNDO. CONSTRUCTOR PUBLIC ProShop(): rGolfer = NEW Golfer(). rGolfer:addScore(79). END CONSTRUCTOR. END CLASS. CLASS Golfer: DEF PRIVATE VAR numRounds AS INTEGER NO-UNDO. CONSTRUCTOR PUBLIC Golfer(): END CONSTRUCTOR. METHOD PUBLIC VOID addScore (INPUT score AS INTEGER): END METHOD. END CLASS. When you invoke an internal procedure from within an external procedure where it is defined, you use a RUN statement that simply names the procedure. When you invoke a user-defined function within an external procedure where it is defined, you name the function in an expression, similar to invoking a method within a class. However, you have to forward reference the definition for the user-defined function if it occurs after the point of invocation. When you invoke an internal procedure defined in another external procedure, you use the RUN statement with an IN option to specify the location of the internal procedure definition. When you invoke a user-defined function defined in another external procedure, you must specify the prototype and reference the location of the function definition, then invoke the function by naming it in an expression. Method invocation within its defining class or on an another object instance is far more consistent than for internal procedures and user-defined functions. Methods never require a separately declared prototype in the class where they are invoked, as user-defined functions sometimes do in the procedure or class where they are invoked. DEV-20: Using Classes and Procedures in OpenEdge 10.1B

30 Invoking Methods Procedure FUNCTION RecalcAverage RETURNS DECIMAL
/* ProShop.p */ DEF VAR hGolfer AS HANDLE NO-UNDO. DEF VAR iAverage AS DECIMAL NO-UNDO. /* Main block code */ RUN Golfer.p PERSISTENT SET hGolfer. iAverage = DYNAMIC-FUNCTION (“RecalcAverage IN hGolfer”, 79). /* Golfer.p */ DEF VAR numRounds AS INTEGER NO-UNDO. /* Main block code */ FUNCTION RecalcAverage RETURNS DECIMAL (INPUT score AS INTEGER): RETURN someAverage. END FUNCTION. When you invoke an internal procedure from within an external procedure where it is defined, you use a RUN statement that simply names the procedure. When you invoke a user-defined function within an external procedure where it is defined, you name the function in an expression, similar to invoking a method within a class. However, you have to forward reference the definition for the user-defined function if it occurs after the point of invocation. When you invoke an internal procedure defined in another external procedure, you use the RUN statement with an IN option to specify the location of the internal procedure definition. When you invoke a user-defined function defined in another external procedure, you must specify the prototype and reference the location of the function definition, then invoke the function by naming it in an expression. Method invocation within its defining class or on an another object instance is far more consistent than for internal procedures and user-defined functions. Methods never require a separately declared prototype in the class where they are invoked, as user-defined functions sometimes do in the procedure or class where they are invoked. DEV-20: Using Classes and Procedures in OpenEdge 10.1B

31 Invoking Methods Class CLASS ProShop: CLASS Golfer:
DEF PRIVATE VAR rGolfer AS CLASS Golfer NO-UNDO. DEF PRIVATE VAR iAverage AS INTEGER NO-UNDO. CONSTRUCTOR PUBLIC ProShop(): rGolfer = NEW Golfer(). iAverage = rGolfer:recalcAverage(79). END CONSTRUCTOR. END CLASS. CLASS Golfer: DEF PRIVATE VAR numRounds AS INTEGER NO-UNDO. CONSTRUCTOR PUBLIC Golfer() END CONSTRUCTOR. METHOD DECIMAL recalcAverage (INPUT score AS INTEGER): END METHOD. END CLASS. When you invoke an internal procedure from within an external procedure where it is defined, you use a RUN statement that simply names the procedure. When you invoke a user-defined function within an external procedure where it is defined, you name the function in an expression, similar to invoking a method within a class. However, you have to forward reference the definition for the user-defined function if it occurs after the point of invocation. When you invoke an internal procedure defined in another external procedure, you use the RUN statement with an IN option to specify the location of the internal procedure definition. When you invoke a user-defined function defined in another external procedure, you must specify the prototype and reference the location of the function definition, then invoke the function by naming it in an expression. Method invocation within its defining class or on an another object instance is far more consistent than for internal procedures and user-defined functions. Methods never require a separately declared prototype in the class where they are invoked, as user-defined functions sometimes do in the procedure or class where they are invoked. DEV-20: Using Classes and Procedures in OpenEdge 10.1B

32 Destruction Procedure /* ProShop.p */ /* Golfer.p */ DEF VAR hGolfer
AS HANDLE NO-UNDO. /* Main block code */ RUN Golfer.p PERSISTENT SET hGolfer. APPLY “CLOSE” TO hGolfer. /* Golfer.p */ DEF VAR scoreXLS AS COM-HANDLE NO-UNDO. /* Main block code */ MainBlock: DO ON ERROR UNDO MainBlock, LEAVE MainBlock: CREATE “Excel.Worksheet" scoreXLS. END. ON CLOSE OF THIS-PROCEDURE DO: RELEASE OBJECT scoreXLS. Using theAssignment (=)statement with the NEW phrase to instantiate a class and assign its object reference is roughly equivalent to running a persistent procedure and setting its procedure object handle using the RUN statement. Just as a procedure-based ABL application that instantiates persistent procedures must begin with a startup procedure file that directly or indirectly (through other procedure files) creates procedure objects, a class-based ABL application must also begin with a startup procedure file that directly or indirectly creates class-based objects. (You cannot directly startup an application with ABL using a class file as you can, for example, with Java.) When it is no longer needed, you can use the DELETE OBJECT statement to destroy either a persistent procedure or an instance of a class VALID-OBJECT function THIS-OBJECT Statement THIS-OBJECT reference DEV-20: Using Classes and Procedures in OpenEdge 10.1B

33 Destruction Class CLASS ProShop: CLASS Golfer: DEF PRIVATE VAR rGolfer
AS CLASS Golfer NO-UNDO. CONSTRUCTOR PUBLIC ProShop(): rGolfer = NEW Golfer(). DELETE OBJECT rGolfer. END CONSTRUCTOR. END CLASS. CLASS Golfer: DEF PRIVATE VAR scoreXLS AS COM-HANDLE NO-UNDO. CONSTRUCTOR PUBLIC Golfer(): initialize(). END CONSTRUCTOR. METHOD VOID initialize(): CREATE “Excel.Worksheet" scoreXLS. END METHOD. DESTRUCTOR PUBLIC Golfer(): RELEASE OBJECT scoreXLS. END DESTRUCTOR. END CLASS. Using theAssignment (=)statement with the NEW phrase to instantiate a class and assign its object reference is roughly equivalent to running a persistent procedure and setting its procedure object handle using the RUN statement. Just as a procedure-based ABL application that instantiates persistent procedures must begin with a startup procedure file that directly or indirectly (through other procedure files) creates procedure objects, a class-based ABL application must also begin with a startup procedure file that directly or indirectly creates class-based objects. (You cannot directly startup an application with ABL using a class file as you can, for example, with Java.) When it is no longer needed, you can use the DELETE OBJECT statement to destroy either a persistent procedure or an instance of a class VALID-OBJECT function THIS-OBJECT Statement THIS-OBJECT reference DEV-20: Using Classes and Procedures in OpenEdge 10.1B

34 Inheritance Procedure /* Golfer.p */ /* Person.p */ DEF VAR hPerson
AS HANDLE NO-UNDO. /* Main block code */ RUN Person.p PERSISTENT SET hPerson. THIS-PROCEDURE:ADD-SUPER-PROCEDURE(hPerson). PROCEDURE GetName: DEFINE INPUT PARAMETER SSNum AS CHAR NO-UNDO. DEFINE OUTPUT PARAMETER GolferName RUN SUPER(INPUT SSNum, OUTPUT Name). END PROCEDURE. /* Person.p */ /* Main block code */ MainBlock: DO ON ERROR UNDO MainBlock, LEAVE MainBlock: END. PROCEDURE GetName: DEFINE INPUT PARAMETER SSNum AS CHAR NO-UNDO. DEFINE OUTPUT PARAMETER personName AS CHARACTER NO-UNDO. FIND person where person.SSNum = SSNum … person-name = person.person-name. END PROCEDURE. Using theAssignment (=)statement with the NEW phrase to instantiate a class and assign its object reference is roughly equivalent to running a persistent procedure and setting its procedure object handle using the RUN statement. Just as a procedure-based ABL application that instantiates persistent procedures must begin with a startup procedure file that directly or indirectly (through other procedure files) creates procedure objects, a class-based ABL application must also begin with a startup procedure file that directly or indirectly creates class-based objects. (You cannot directly startup an application with ABL using a class file as you can, for example, with Java.) When it is no longer needed, you can use the DELETE OBJECT statement to destroy either a persistent procedure or an instance of a class VALID-OBJECT function THIS-OBJECT Statement THIS-OBJECT reference DEV-20: Using Classes and Procedures in OpenEdge 10.1B

35 Inheritance Class CLASS Golfer INHERITS Person:
CONSTRUCTOR PUBLIC Golfer(): SUPER(). END CONSTRUCTOR. METHOD PUBLIC OVERRIDE CHAR GetName (INPUT SSNum AS CHAR): DEF VAR golferName AS CHA NO-UNDO. golferName = SUPER:GetName(SSNum). return golferName. END METHOD. END CLASS. CLASS Person: CONSTRUCTOR PUBLIC Person(): initialize(). END CONSTRUCTOR. METHOD VOID initialize(): /* initialization code */ END METHOD. METHOD PUBLIC CHAR GetName (INPUT SSNum AS CHAR): FIND person WHERE person.SSNum = SSNum … return person.personName END CLASS. Using theAssignment (=)statement with the NEW phrase to instantiate a class and assign its object reference is roughly equivalent to running a persistent procedure and setting its procedure object handle using the RUN statement. Just as a procedure-based ABL application that instantiates persistent procedures must begin with a startup procedure file that directly or indirectly (through other procedure files) creates procedure objects, a class-based ABL application must also begin with a startup procedure file that directly or indirectly creates class-based objects. (You cannot directly startup an application with ABL using a class file as you can, for example, with Java.) When it is no longer needed, you can use the DELETE OBJECT statement to destroy either a persistent procedure or an instance of a class VALID-OBJECT function THIS-OBJECT Statement THIS-OBJECT reference DEV-20: Using Classes and Procedures in OpenEdge 10.1B

36 Constructor Overloading
Procedure Class /* Golfer.p */ /* One and only Main block code */ MainBlock: DO ON ERROR UNDO MainBlock, LEAVE MainBlock: END. CLASS Golfer: CONSTRUCTOR PUBLIC Golfer(): /* constructor code */ END CONSTRUCTOR. CONSTRUCTOR PUBLIC Golfer (INPUT Name AS CHAR, INPUT Handicap AS INTEGER): /* different constructor code */ END CLASS. Using theAssignment (=)statement with the NEW phrase to instantiate a class and assign its object reference is roughly equivalent to running a persistent procedure and setting its procedure object handle using the RUN statement. Just as a procedure-based ABL application that instantiates persistent procedures must begin with a startup procedure file that directly or indirectly (through other procedure files) creates procedure objects, a class-based ABL application must also begin with a startup procedure file that directly or indirectly creates class-based objects. (You cannot directly startup an application with ABL using a class file as you can, for example, with Java.) When it is no longer needed, you can use the DELETE OBJECT statement to destroy either a persistent procedure or an instance of a class VALID-OBJECT function THIS-OBJECT Statement THIS-OBJECT reference DEV-20: Using Classes and Procedures in OpenEdge 10.1B

37 Method Overloading Procedure Class /* Golfer.p */ CLASS Golfer:
/* Main block code */ PROCEDURE GetName: DEFINE INPUT PARAMETER SSNum AS CHAR NO-UNDO. DEFINE OUTPUT PARAMETER GolferName END PROCEDURE. DEFINE INPUT PARAMETER MemberID AS INTEGER NO-UNDO. CLASS Golfer: CONSTRUCTOR PUBLIC Person(): /* constructor code */ END CONSTRUCTOR. METHOD PUBLIC CHAR GetName (INPUT SSNum AS CHAR): END METHOD. (INPUT MemberID AS INTEGER): END CLASS. Using theAssignment (=)statement with the NEW phrase to instantiate a class and assign its object reference is roughly equivalent to running a persistent procedure and setting its procedure object handle using the RUN statement. Just as a procedure-based ABL application that instantiates persistent procedures must begin with a startup procedure file that directly or indirectly (through other procedure files) creates procedure objects, a class-based ABL application must also begin with a startup procedure file that directly or indirectly creates class-based objects. (You cannot directly startup an application with ABL using a class file as you can, for example, with Java.) When it is no longer needed, you can use the DELETE OBJECT statement to destroy either a persistent procedure or an instance of a class VALID-OBJECT function THIS-OBJECT Statement THIS-OBJECT reference DEV-20: Using Classes and Procedures in OpenEdge 10.1B

38 Inheritance Data Member & Property scoping within a Class Hierarchy (Protected) Method scoping within a Class Hierarchy Method Overriding Method & Constructor Overloading Procedures do not support Interfaces, Method Overloading, or Constructor Overloading. DEV-20: Using Classes and Procedures in OpenEdge 10.1B

39 THIS-PROCEDURE vs. THIS-OBJECT
/* ProShop.p */ DEF VAR hGolfer AS HANDLE NO-UNDO. /* Main block code */ RUN Golfer.p PERSISTENT SET hGolfer. RUN setProShop IN hGolfer (INPUT THIS-PROCEDURE). /* Golfer.p */ DEF VAR hProShop AS HANDLE NO-UNDO. /* Main block code */ PROCEDURE setProShop: DEF INPUT PARAM hProc hProShop = hProc. END PROCEDURE. Using theAssignment (=)statement with the NEW phrase to instantiate a class and assign its object reference is roughly equivalent to running a persistent procedure and setting its procedure object handle using the RUN statement. Just as a procedure-based ABL application that instantiates persistent procedures must begin with a startup procedure file that directly or indirectly (through other procedure files) creates procedure objects, a class-based ABL application must also begin with a startup procedure file that directly or indirectly creates class-based objects. (You cannot directly startup an application with ABL using a class file as you can, for example, with Java.) When it is no longer needed, you can use the DELETE OBJECT statement to destroy either a persistent procedure or an instance of a class VALID-OBJECT function THIS-OBJECT Statement THIS-OBJECT reference DEV-20: Using Classes and Procedures in OpenEdge 10.1B

40 THIS-PROCEDURE vs. THIS-OBJECT
CLASS ProShop: DEF PRIVATE VAR rGolfer AS CLASS Golfer NO-UNDO. CONSTRUCTOR PUBLIC ProShop(): rGolfer = NEW Golfer(). rGolfer:SetProShop(THIS-OBJECT). END CONSTRUCTOR. END CLASS. CLASS Golfer: DEF PRIVATE VAR rProShop AS CLASS ProShop NO-UNDO. METHOD PUBLIC VOID SetProShop (INPUT rObject AS CLASS ProShop): rProShop = rObject. END METHOD. END CLASS. DEV-20: Using Classes and Procedures in OpenEdge 10.1B

41 Procedure & Class Interoperability
Object references and a procedure handles represent two very different constructs Cannot execute r-code for a class using the RUN statement. Must use the NEW phrase. Cannot use the NEW phrase to run a persistent procedure. An instance of a class never has a procedure object handle associated with it. So there is no THIS-PROCEDURE or TARGET-PROCEDURE or SOURCE-PROCEDURE handles A procedure has no notion of a class or object reference. So there is no THIS-OBJECT reference Cannot assign a procedure handle to an object reference. Cannot assign an object reference to a procedure handle. Cannot cast a procedure handle to an object reference or an object reference to a procedure handle. DEV-20: Using Classes and Procedures in OpenEdge 10.1B

42 Procedure & Class Interoperability
Cannot pass an object reference to a routine expecting a procedure handle. Cannot pass a procedure handle to a routine expecting an object reference. Cannot define methods in a procedure, only in classes Cannot define internal procedure or user-defined functions in classes, only in external procedures. Cannot use the object-reference:method-name syntax to run an internal procedure or a function, but only a method. But can use this syntax in both classes and procedures. Cannot define a constructor or destructor for a procedure, only in classes. Cannot specify a PUBLIC, PRIVATE, or PROTECTED access mode on a class member except in the main block of a class. DEV-20: Using Classes and Procedures in OpenEdge 10.1B

43 Procedure & Class Interoperability
Cannot use ADD-SUPER-PROCEDURE( ) method on the THIS-OBJECT or THIS-PROCEDURE handle within a class. Cannot add a class-based object as a super procedure. But within a class, can use the SESSION:ADD-SUPER-PROCEDURE( ) method to extend the super procedure chain of the SESSION handle. And can use the procedure-handle:ADD-SUPER-PROCEDURE( ) method, where procedure-handle is a procedure object handle set from running a persistent procedure, in order to extend the super procedure chain for other, procedure objects. DEV-20: Using Classes and Procedures in OpenEdge 10.1B

44 Using a Class in a Procedure
Define a global (to the procedure) variable as a class DEF VAR rGolfer AS Golfer. rGolfer = NEW Golfer(). RUN InternalProcA. PROCEDURE InternalProcA: DEF VAR rLocalGolfer AS Golfer. rLocalGolfer = NEW Golfer(). rLocalGolfer:addScore(79). rGolfer:recalcAverage(79). RUN InternalProcB(INPUT rLocalGolfer ). END PROCEDURE. PROCEDURE InternalProcB: DEF INPUT PARAMETER rParamGolfer AS Golfer. rParamGolfer:calcPutts(32). Instantiate an instance Define a local variable as a class Instantiate a second instance Call method on local variable Call method on global variable Call procedure passing class as parameter Define parameter as a class Call a method on the parameter DEV-20: Using Classes and Procedures in OpenEdge 10.1B

45 Using a Procedure in a Class
CLASS ProShop: DEF VAR hProc AS HANDLE NO-UNDO. CONSTRUCTOR PUBLIC ProShop(): RUN Golfer.p PERSISTENT SET hProc. END CONSTRUCTOR. METHOD PUBLIC VOID ProcessGolfer(): RUN addScore(INPUT 79) IN hProc. RUN getPreviousScore.p. DEF VAR y AS DECIMAL NO-UNDO. y = DYNAMIC-FUNCTION("recalcAverage IN hProc", 79). END METHOD. DESTRUCTOR PUBLIC Proshop(): APPLY "CLOSE" TO hProc. END DESTRUCTOR. END CLASS. Run a procedure persistently Run an internal procedure Run an external procedure Use function dynamically Processing procedure events DEV-20: Using Classes and Procedures in OpenEdge 10.1B

46 Error Handling Other OO languages have try… catch…
How to trap errors? Other OO languages have try… catch… We will have something like it too RETURN ERROR, NO-ERROR, ON-ERROR and ERROR-STATUS all continue to work with Classes DEV-20: Using Classes and Procedures in OpenEdge 10.1B

47 Error Handling in Procedures & Methods
/* ProShop.p */ DEF VAR hGolfer AS HANDLE NO-UNDO. /* Main block code */ RUN Golfer.p PERSISTENT SET hGolfer. RUN addScore(INPUT score) IN hGolfer NO-ERROR. IF ERROR-STATUS:ERROR THEN DO: IF RETURN-VALUE = “Too High” THEN ELSE .. END. /* Golfer.p */ PROCEDURE AddScore: DEF INPUT PARAM newScore AS INT NO-UNDO. IF newScore < 59 THEN RETURN ERROR. ELSE IF newScore > 150 THEN RETURN ERROR “Try again”. END PROCEDURE. Using theAssignment (=)statement with the NEW phrase to instantiate a class and assign its object reference is roughly equivalent to running a persistent procedure and setting its procedure object handle using the RUN statement. Just as a procedure-based ABL application that instantiates persistent procedures must begin with a startup procedure file that directly or indirectly (through other procedure files) creates procedure objects, a class-based ABL application must also begin with a startup procedure file that directly or indirectly creates class-based objects. (You cannot directly startup an application with ABL using a class file as you can, for example, with Java.) When it is no longer needed, you can use the DELETE OBJECT statement to destroy either a persistent procedure or an instance of a class VALID-OBJECT function THIS-OBJECT Statement THIS-OBJECT reference DEV-20: Using Classes and Procedures in OpenEdge 10.1B

48 Error Handling in Procedures & Methods
Class CLASS ProShop: DEF PRIVATE VAR rGolfer AS CLASS Golfer NO-UNDO. CONSTRUCTOR PUBLIC ProShop(): rGolfer = NEW Golfer(). ProcessScore(79). END CONSTRUCTOR. METHOD PUBLIC VOID ProcessScore (INPUT score AS INTEGER): rGolfer:addScore(79) NO-ERROR. IF ERROR-STATUS:ERROR THEN DO: IF RETURN-VALUE = “Too High” THEN … ELSE … END. END METHOD. END CLASS. CLASS Golfer: DEF PRIVATE VAR numRounds AS INTEGER NO-UNDO. CONSTRUCTOR PUBLIC Golfer(): /* constructor code */ END CONSTRUCTOR. METHOD PUBLIC VOID addScore (INPUT score AS INTEGER): IF newScore < 59 THEN RETURN ERROR. ELSE IF newScore > 150 THEN RETURN ERROR “Try again”. END METHOD. END CLASS. Using theAssignment (=)statement with the NEW phrase to instantiate a class and assign its object reference is roughly equivalent to running a persistent procedure and setting its procedure object handle using the RUN statement. Just as a procedure-based ABL application that instantiates persistent procedures must begin with a startup procedure file that directly or indirectly (through other procedure files) creates procedure objects, a class-based ABL application must also begin with a startup procedure file that directly or indirectly creates class-based objects. (You cannot directly startup an application with ABL using a class file as you can, for example, with Java.) When it is no longer needed, you can use the DELETE OBJECT statement to destroy either a persistent procedure or an instance of a class VALID-OBJECT function THIS-OBJECT Statement THIS-OBJECT reference DEV-20: Using Classes and Procedures in OpenEdge 10.1B

49 Global Variables Other OO languages have STATIC
How to set session-wide variables? Other OO languages have STATIC We will too – in the future Need access to existing global variables Cannot be accessed in directly within classes OO-Procedural interoperability helps DEV-20: Using Classes and Procedures in OpenEdge 10.1B

50 Global Variables Example – Procedural Side
Globals.p DEF NEW GLOBAL SHARED VAR gcPGA-ID AS CHAR NO-UNDO. FUNCTION getPGA-ID RETURNS CHAR (): RETURN gcPGA-ID. END FUNCTION. FUNCTION setPGA-ID RETURNS LOGICAL (INPUT pcPGA-ID AS CHAR): gcPGA-ID = pcPGA-ID. DEV-20: Using Classes and Procedures in OpenEdge 10.1B

51 Global Variables Example – OO Side
CLASS Golfer: DEF VAR hGlobal AS HANDLE NO-UNDO. CONSTRUCTOR PUBLIC Golfer(): RUN Globals.p PERSISTENT SET hGlobal. END CONSTRUCTOR. METHOD PUBLIC VOID processPGA-ID(): DEF VAR pga-id AS CHAR NO-UNDO. DYNAMIC-FUNCTION(“setPGA-ID IN hGlobal”, pga-id). pga-id = DYNAMIC-FUNCTION(“getPGA-ID IN hGlobal”). END METHOD. DESTRUCTOR PUBLIC Golfer(): DELETE PROCEDURE hGlobal. END DESTRUCTOR. END CLASS. Starts the global variables procedure persistently! Public getter and setter methods DEV-20: Using Classes and Procedures in OpenEdge 10.1B

52 Include Files /* ProShop.p */ /* dsCart.i */ DEF VAR hGolfer
AS HANDLE NO-UNDO. {dsCart.i &RO=REFERENCE-ONLY} /* Main block code */ RUN Golfer.p PERSISTENT SET hGolfer. /* dsCart.i */ DEF TEMP-TABLE ttCart {&RO} FIELD regNo AS CHAR FIELD purchaseDate AS DATE. DEF DATASET dsCart {&RO} FOR ttCart. DEV-20: Using Classes and Procedures in OpenEdge 10.1B

53 Include Files /* dsCart.i */ DEF TEMP-TABLE ttCart {&RO}
CLASS ProShop: DEF PRIVATE VAR rGolfer AS CLASS Golfer NO-UNDO. {dsCart.i &RO=REFERENCE-ONLY} CONSTRUCTOR PUBLIC ProShop(): END CONSTRUCTOR. METHOD PUBLIC VOID ProcessScore (INPUT score AS INTEGER): END METHOD. END CLASS. /* dsCart.i */ DEF TEMP-TABLE ttCart {&RO} FIELD regNo AS CHAR FIELD purchaseDate AS DATE. DEF DATASET dsCart {&RO} FOR ttCart. DEV-20: Using Classes and Procedures in OpenEdge 10.1B

54 Preprocessor Names & Directives
All preprocessor directives, such as &IF, &GLOBAL-DEFINE, and &SCOPED-DEFINE, can be used in classes and behave as they do in procedures. All built-in preprocessor names are supported in classes including BATCH-MODE, FILE-NAME, LINE-NUMBER, OPSYS, SEQUENCE and WINDOW-SYSTEM. DEV-20: Using Classes and Procedures in OpenEdge 10.1B

55 Preprocessor Names & Directives
/* ProShop.p */ {defines.i} DEF VAR maxGolfers AS INTEGER INITIAL {&MAX-GOLFERS} NO-UNDO. DEF VAR hGolfer AS HANDLE NO-UNDO. /* Main block code */ RUN Golfer.p PERSISTENT SET hGolfer. /* defines.i */ &GLOBAL-DEFINE MAX-GOLFERS 100 DEV-20: Using Classes and Procedures in OpenEdge 10.1B

56 Preprocessor Names & Directives
CLASS ProShop: {defines.i} DEF VAR maxGolfers AS INTEGER INITIAL {&MAX-GOLFERS} NO-UNDO. DEF PRIVATE VAR rGolfer AS CLASS Golfer NO-UNDO. CONSTRUCTOR PUBLIC ProShop(): /* constructor code */ END CONSTRUCTOR. METHOD PUBLIC VOID ProcessScore (INPUT score AS INTEGER): END METHOD. END CLASS. /* defines.i */ &GLOBAL-DEFINE MAX-GOLFERS 100 DEV-20: Using Classes and Procedures in OpenEdge 10.1B

57 Defining Widgets & Handling Events
/* Golfer.p */ DEFINE BUTTON msg. DEFINE BUTTON done. DEFINE FRAME f msg done. ON 'choose':U OF msg IN FRAME f DO: MESSAGE "click" VIEW-AS ALERT-BOX. END. MainBlock: DO ON ERROR UNDO MainBlock, LEAVE MainBlock: ENABLE ALL WITH FRAME f. WAIT-FOR CHOOSE OF done. CLASS Golfer: DEFINE PRIVATE BUTTON msg. DEFINE PRIVATE BUTTON done. DEFINE FRAME f msg done. ON 'choose':U OF msg IN FRAME f DO: MESSAGE "click" VIEW-AS ALERT-BOX. END. CONSTRUCTOR PUBLIC Golfer ( ): ModalDisplay ( ). END CONSTRUCTOR. METHOD PRIVATE VOID ModalDisplay ( ): ENABLE ALL WITH FRAME f. WAIT-FOR CHOOSE OF done. END METHOD. END CLASS. DEV-20: Using Classes and Procedures in OpenEdge 10.1B

58 Handling Events – ON statement
/* Golfer.p */ DEF VAR numRounds AS INT NO-UNDO. /* Main block code */ RUN teeOff. PROCEDURE teeoff: END PROCEDURE. ON CLOSE OF THIS-PROCEDURE DO: END. CLASS Driver: DEFINE PRIVATE BUTTON msg. DEFINE PRIVATE BUTTON done. DEFINE FRAME f msg done. ON 'choose':U OF msg IN FRAME f DO: MESSAGE "click" VIEW-AS ALERT-BOX. END. CONSTRUCTOR PUBLIC Driver ( ): ModalDisplay ( ). END CONSTRUCTOR. METHOD PRIVATE VOID ModalDisplay ( ): ENABLE ALL WITH FRAME f. WAIT-FOR CHOOSE OF done. END METHOD. END CLASS. DEV-20: Using Classes and Procedures in OpenEdge 10.1B

59 Some Additional Items for You to Research
SET-CALLBACK() using Class methods Using WIDGET POOLS SESSION:FIRST-OBJECT, LAST-OBJECT Packages vs. Propath directories Compiler Options DEV-20: Using Classes and Procedures in OpenEdge 10.1B

60 In Summary Classes and procedures are not so different
However there are key distinctions and benefits Classes and procedures can work together very well You can keep all of your existing procedures And start developing using classes today DEV-20: Using Classes and Procedures in OpenEdge 10.1B

61 For More Information, go to…
PSDN Implementing the OpenEdge Reference Architecture with Classes Progress eLearning Community What's New OE 10.1 Object Oriented Programming Documentation 10.1B Object-oriented Programming manual 10.1B New and Revised Features manual DEV-20: Using Classes and Procedures in OpenEdge 10.1B

62 Relevant Exchange Sessions
DEV-6: Getting Started with Object-Oriented Programming DEV-12: Object-Oriented Programming in OpenEdge ABL ARCH-7: A Class-Based Implementation of the OERA ARCH-12: Leveraging Design Patterns in ABL Applications DEV-20: Using Classes and Procedures in OpenEdge 10.1B

63 Questions? DEV-20: Using Classes and Procedures in OpenEdge 10.1B

64 Thank you for your time DEV-20: Using Classes and Procedures in OpenEdge 10.1B

65 DEV-20: Using Classes and Procedures in OpenEdge 10.1B


Download ppt "DEV-20: Using Classes and Procedures in OpenEdge® 10.1B"

Similar presentations


Ads by Google