Application Classes

This chapter provides an overview of application classes and discusses the following topics:

Click to jump to parent topicUnderstanding Application Classes

You can create Application Packages in Application Designer. These packages contain application classes (and may contain other packages also). An application class, at its base level, is just a PeopleCode program. However, using the Application Packages, you can create your own classes, and extend the functionality of the existing PeopleCode classes.

The application classes provide capability beyond that offered by the existing PeopleCode classes. Unlike the existing classes, a subclass can inherit all the properties and methods of the class it extends. This provides all the advantages of true object-oriented programming:

In addition, the application classes provide more structure. Using the Application Packages, you have a clear definition of each class, as well as its listed properties and methods. This makes it easier to create a complex program that uses many functions.

See Also

Creating Application Packages and Classes

Click to jump to top of pageClick to jump to parent topicWhen Would You Use Application Classes?

Use Application classes to help structure your existing PeopleCode functions. For example, prior to Application classes, most PeopleCode functions were put into FUNCLIB records. However, in larger, more complex programs, it is sometimes difficult to find (let alone maintain) a function. You could make every function a class in a package with very little reworking of your PeopleCode (as well as making the different fields in a record a package, and combining them into a single larger package.) This provides a better visual interface for grouping your functions.

In addition, use Application classes when you have to do generic processing, and just the details are different. For example, suppose one of the processes for your application is reading a file object and doing bulk insert. The process could all be contained in a single package, with the classes and subclasses providing all the details, different kinds of reading for different types of files, different inserts based on the record, and so on.

One of the main differences between a class and a function call is that the call to the class is dynamic, like a function variable, but more closely controlled. All the calls to the class (methods) must have the same signature.

For example, suppose you want to provide a more generic sort, with comparison function at the end of it. You want to use the array class Sort method, but your process has to be generic: you aren't certain if you're comparing two records or two strings. You could define a class that had as its main method a comparison, and return a -1, 0, or 1. Then write your personalized sort, extending the array class method Sort.

Another use is for business processing. Think in terms of core functionality, with vertical product solutions that extend the basic processing by providing specifics, in other words, by extending the general classes with subclasses. This could be appropriate for sales force automation or order entry.

Generally, use application classes where you can extract the common functionality.

Note. Do not extend a SOAPDoc with an application class. This is currently not supported.

Click to jump to parent topicApplication Classes General Structure

All application classes are contained in a package. All application classes are composed of PeopleCode. In this section, we discuss the general form of an application class, which is:

This division enables a separation of the following:

The data types used in an application class (for methods parameters, return values, and so on) can be any PeopleCode types, including application classes. Likewise, application classes can be used anywhere in a PeopleCode program where a general data type can be used.

See Also

Data Types

Click to jump to top of pageClick to jump to parent topicClass Name

Application classes have a fully qualified name that is formed hierarchically by the name of the top-level package that contains them, the package that contains that package, and so on down to the short class name, that is, the one specified when the class was created in Application Designer, using a colon for the separator between names.

The fully qualified name of the class must be unique, as this is what identifies the class. The short name of the class does not have to be unique.

For example, suppose package CRM contains the application classes Address and Customer as well as the package Utilities, which in turn contains the application classes Address and Incident:

Application classes example

There are four distinct application classes in this example:

Note. If you change the name of a package or an application class, that name change is not automatically propagated through all your PeopleCode programs. You must make the change manually in your programs. If you specify an incorrect name for a package or application class, you receive a warning when you try to save the PeopleCode.

Click to jump to top of pageClick to jump to parent topicClass Extension

Extension represents the "is-a" relationship. When a class extends another class, it's called a subclass of that class. Conversely, the class being extended is called a superclass of that subclass.

A subclass inherits all of the public methods and properties (collectively called members) of the class it extends. These members can be overridden by declarations of methods and properties in the subclass.

Note. Application classes have no multiple inheritance (that is, being able to extend more than one class.)

Type checking in PeopleCode (both at design time and runtime) does strong type checking of application classes, tracking each application class as a separate type. A subclass can be used as the class it extends, because it implements the public interfaces of its superclass. This is called subtyping.

In the following example, the class Banana extends the class Fruit. Banana is the subclass of Fruit. From Fruit, you can extend to Bananas. However, from Bananas you can't extend to Fruit. Another way to think about this is you can only extend from the general to the specific, not the other way around.

class Fruit method DoFruit(); property number FruitNum instance; end-class; ​class Banana extends Fruit ​method DoBanana(); property number BananaNum instance; end-class;

The following code shows a correct way to assign a class object, because Banana is a subtype of Fruit.

local Fruit &Bref = Create Banana();

The following is not correct. Banana is a subtype of Fruit. Fruit is not a subtype of Banana. This assignment causes an error at design time.

local Banana &Fref = Create Fruit();

Before you can extend a class, you must first import it. You must import all class names you use in a PeopleCode program before you use them.

See Also

Import Declarations

Click to jump to top of pageClick to jump to parent topicDeclaration of Public External Interface

The names of the members (that is, all the methods and properties of a class) must be unique only within that class. Different classes can have members with the same name. As members are used only with objects, and each object knows its class, the member that's accessed is the one associated with that class.

For example, more than one class has the property Name which returns the name of the object executing the property. There isn't any confusion, because the field Name property returns the name of a field, while the record name property returns the name of a record. No class has more than one property called Name.

Note. Within a class, each member name must be unique.

The public part of a class declaration specifies the methods and properties that the class provides to other PeopleCode programs. These methods and properties are dynamically bound, that is, the actual method that is called depends on the actual class of the object, as it might be an overridden method or property from a subclass.

In the following code example, the text in bold indicates the public part of the class declaration.

/* generic building class */ class BuildingAsset ​method Acquire (); method DisasterPrep(); ​end-class;

Click to jump to top of pageClick to jump to parent topicAccess Control and the Declaration of Protected Properties and Methods

Application class objects have private and public access control. Properties or methods that are declared outside the “private” declaration section have public access control. This means that they can be referenced and used by any PeopleCode. This access is of course subject to access controls such as “readonly”. Private properties and methods are private to the class, not instance, and can only be referenced by objects of this application class.

Between these two access control schemes of public and private, lies the concept of protected methods and properties. Protected methods and properties can be accessed only by objects of this application class and those derived from this application class. Use protected methods or properties when you want to hide them from outside use, but allow the flexibility of using them in derived classes.

The declarations of protected variables and methods are done within the class declaration, before the declaration of private variables and methods. You can use protected instance variables in interface classes. Protected methods and properties can be overridden by subclasses.

Most of the time your design can be implemented through the use of private methods and properties without resorting to the use of protected methods and properties. The following examples demonstrates the rules and some of the subtleties about when to use protected methods and properties.

class A; method A(); property string Q; protected method MP() Returns string; property string p; end-class; method A; &p = "Class A: property p"; end-method; method MP /+ Returns String +/ Return "Class A: method MP"; end-method; ==================== class B extends A; method B(); method M(&X As C); method m2(&Aobj As A); /* property string P; */ protected property string Q; method MP() Returns string; end-class; method B; %Super = (create A()); &Q = "Class B: property Q"; /* &P = "Class B: property P";*/ end-method; method M /+ &X as FOXTEST:C +/; MessageBox(0, "", 0, 0, "In B:M %This.P=" | %This.p); /* %This.p is class A property P */ MessageBox(0, "", 0, 0, "In B:M %This.Q=" | %This.Q); /* %This.q is class B property Q */ MessageBox(0, "", 0, 0, %This.MP()); /* %This.MP() calls class B method MP */ if &X.p = "Error" then end-if; /* error: cannot reference &X.p since class B is not involved in the implementation of class C */ end-method; method m2 /+ &Aobj as FOXTEST:A +/ /* MessageBox(0, "", 0, 0, "In B:M2 &Aobj.P=" | &Aobj.p); /* Error: cannot reference &Aobj.p from class B since class B is not involved in its implementation */ End-method; method MP /+ Returns String +/ Return "Class B: method MP"; end-method; ======================= class C extends A; method C(); protected property string P; end-class; method C; %Super = (create A()); &P = "Class C: property P"; end-method; ========================== /* AE program */ import FOXTEST:*; Local A &A = (create A()); Local object &obj = &A; MessageBox(0, "", 0, 0, "In AEMINITEST: &Obj.p=" | &obj.P); /* run time error: anonymous access through type object not allowed*/

The following example also illustrates some of the rules surrounding protected access control.

import FOXTEST:Point3d; class Point method Point(&X1 As integer, &Y1 As integer); method Warp(&A As Point3d); protected property integer x; property integer y; end-class; method Point /+ &X1 as Integer, +/ /+ &Y1 as Integer +/; %This.x = &X1; %This.y = &Y1; end-method; method Warp /+ &A as FOXTEST:Point3d +/ /* Local Integer &temp = &A.Z; ERROR cannot access &A.Z */ end-method; ================================ import FOXTEST:Point; class Point3d extends Point method Point3d(&X1 As integer, &Y1 As integer, &Z1 As integer); method Delta(&P As Point); method Delta3d(&Q As Point3d); protected property integer z; end-class; method Point3d /+ &X1 as Integer, +/ /+ &Y1 as Integer, +/ /+ &Z1 as Integer +/; %Super = (create Point(&X1, &Y1)); %This.z = &Z1; end-method; method Delta /+ &P as FOXTEST:Point +/ /* &P.x = %This.x; ERROR cannot access &P.x since while Point3d (the class in which references to fields x and y occur) is a subclass of Point (the class in which x and y are declared), it is not involved in the implementation of Point (the type of parameter p)*/ /* &P.y = %This.y; ERROR cannot access &P.y. Same reason as above */ end-method; method Delta3d /+ &Q as FOXTEST:Point3d +/ /* The protected members of Q can be accessed because the class point3d is a⇒ subclass of Point and is involved in the implementation of Point3d */ &Q.x = %This.x; &Q.y = %This.y; &Q.z = %This.z; end-method;

Click to jump to top of pageClick to jump to parent topicDeclaration of Private Instance Variables and Methods

The private part of a class declaration gives the declaration of any private methods, instance variables, and private class constants. Private methods cannot be overridden by subclasses, because they are completely private to the declaring class. Likewise, the instance variables can't be overridden.

The declarations of private variables and methods are done within the class declaration.

Note. You cannot have private methods or instance variables in an interface type of class.

In the following example, there are both public as well as private methods and properties. Any method that is declared before the keyword Private in the initial class declaration is public. Any method declared after the keyword Private is private. Properties are only declared in Public. Instances and Constants are only declared in Private

In the following example, the class Example extends the class ExampleBase. It has both public as well as private methods and properties. It also defines the private method in the definition of methods section of the code (the private definitions are marked like this.)

import PWWPACK:ExampleBase; class Example extends ExampleBase method Example(); method NumToStr(&Num As number) Returns string; method AppendSlash(); property number SlashCount get; property number ImportantDayOfWeek get set; property string SlashString readonly; property date ImportantDate; ​private method NextDayOfWeek(&Dow As number) Returns date; Constant &Sunday = 1; instance string &BaseString; ​end-class; Global string &CurrentBaseString; /* Method declarations */ method NumToStr return String(&num); end-method; method AppendSlash &SlashString = &SlashString | "/"; end-method; get SlashCount Return Len(&SlashString) - Len(&BaseString); end-get; get ImportantDayOfWeek Return Weekday(&ImportantDate); end-get; set ImportantDayOfWeek &importantdate = %This.nextdayofweek(&newvalue); end-set; ​/* Private method. */ method nextdayofweek Return &ImportantDate + (&dow - Weekday(&ImportantDate)); end-method; ​/* Constructor. */ method Example &BaseString = &CurrentBaseString; &SlashString = &BaseString; &ImportantDate = Date(19970322); end-method;

Click to jump to top of pageClick to jump to parent topicDefinition of Methods

After the declaration of any global or component variables and external functions needed by the methods, comes the actual definition of the methods. This section discusses some of the differences in how application programs are processed by the system, and how application class method parameters are processed.

Not Skipping to The Next Top-Level Statement

For existing functions and programs, the system skips to the next top-level statement in some circumstances, such as a field not found error. This never happens in an application class program. The code is always executed or an error is produced.

Passing Parameters in Application Class Methods

The parameters to a method are passed by value in the absence of an out specification in the parameter list. However, if a parameter list has an out specification, that argument (when used in the call of a method) must be a value that can be assigned something, and is passed by reference. In particular this means you cannot pass an object property to a method which requires the parameter to be an "out" parameter. Application class properties are always passed by value.

For example:

/* argument passed by reference */ method increment(&value as number out); /* argument passed by value */ method increment(&value as number);

This is in contrast with existing PeopleCode functions that pass all parameters by reference when they can be assigned something. This means the method signature is a specification of which parameters can be updated by the method. This makes the code easier to debug and maintain because it's easy to see what can be updated and what can't.

The following is an example of code that increments a variable by one.

local Number &Mine; &Mine = 1; &obj.Increment(&Mine);

&Mine now has the value 2.

You cannot pass properties by reference. For example, supposed MyProp is a property of class Xan, a statement that requires a reference doesn't work if you supply the property. The following code will always fail because &Xan.MyProp is always passed by value and the MySqlExec method requires it to be passed by reference (so a value can be returned.)

MySqlExec("select from bar", &Xan.MyProp)

This makes sense because the semantics of an object require that you can only change a property with standard property references, not as a side affect of some other action.

Passing Parameters with Object Data Types

Parameters with object data types are always passed by reference:

/* argument passed by reference */ method storeInfo(&f as File);

If you specify the out modifier for a method parameter with an object data type, it becomes a reference parameter. This means that the parameter variable is passed by reference instead of the object that it is pointing at when passed.

For example, if you pass an object parameter with the out modifier:

method myMethod(&arg as MyObjectClass); Local MyObjectClass &o1 = create MyObjectClass("A"); Local MyOtherObjectClass &o2 = create MyOtherObjectClass(); &o2.myMethod(&o1);

And inside myMethod this occurs:

Method myMethod &arg = create MyObjectClass("B"); end-method;

Since the method argument is reassigned within the body of myMethod, &o1 does not point at the new instance of MyObjectClass (initialized with "B") after the method call completes. This is because &o1 still references the original instance of MyObjectClass.

However, if &o1 had been passed with the out modifier, after the method call completes, &o1 points at whatever the parameter was last assigned to; in this case, the new instance of MyObjectClass. The parameter, rather than the object, is passed by reference.

Using the Out Specification for a Parameter

In the following example, a class, AddStuff, has a single public method, DoAdd. This adds two numbers together, then assigns them as different numbers. In the signature of the method declaration, the first parameter is not declared with an out statement, while the second one is.

class AddStuff ​method DoAdd(&P1 as number, &P2 as number out); ​end-class; method DoAdd &X = &P1 + &P2; &P1 = 1; &P2 = 2; end-method;

In the following PeopleCode example, an object named &Aref is instantiated from the class AddStuff. Two parameters, &I and &J are also defined.

local AddStuff &Aref = Create AddStuff(); local number &I = 10; local number &J = 20;

The following code example is correct. &J is changed, because of the outstatement in the method signature, and because the value is being passed by reference. The value of &I is not updated.

&Aref.DoAdd(&I, &J); /* changes &J but not &I */

The following code example causes a design time error. The second parameter must be passed by reference, not by value.

&Aref.DoAdd(10, 20); /* error - second argument not variable */

See Also

Understanding the PeopleCode Language

Click to jump to top of pageClick to jump to parent topicDeclaration of Abstract Methods and Properties

You can declare methods and properties as abstract, that is, a method or property that has a signature which specifies the parameters and results, but has no implementation in the class that defines it. The implementation may occur in one of the classes that extend the class where the method or property is initially defined.

Abstract methods and properties could be used, for example, when your application wants to provide a means for in-field customization. Your application might deliver a base class specifying the abstract methods and properties and you would allow the customization to complete those methods and properties by using a class that would extend the base class and provide implementations for some or all of the abstract methods and properties.

For a class that only contains abstract methods and properties, that is, a pure interface class, you would define a PeopleCode interface, instead of a class. You define a PeopleCode interface by using the keyword Interface instead of Class. In an interface, all the methods and properties are abstract by default.

The following example illustrates the use of abstract methods and properties. Class MyInterface is the base class which has mostly abstract methods and properties. However it is fully specified by the class MyImplementation which provides and implementation for all the methods and properties.

class MyInterface method MyMethod1() abstract; method MyMethod2() Returns string abstract; method MyMethod3(); property string myproperty1 abstract readonly; property number myproperty2 abstract; property number myproperty3 abstract; end-class; method MyMethod3 end-method; ------------------------------------------------------------------- import FOXTEST:MyInterface; class MyImplementation extends MyInterface; method MyImplementation(); method MyMethod1(); method MyMethod2() Returns string; property string myproperty1 readonly; property number myproperty2; property number myproperty3; end-class; method MyImplementation %Super = Create MyInterface();[Ugh.] end-method; method MyMethod1 /* dummy */ end-method; method MyMethod2 /+ Returns String +/ Return "MyMethod2's implementation is this"; end-method;

Considerations Using Abstract Methods and Properties

Be aware of the following considerations when using abstract methods or properties.

Click to jump to top of pageClick to jump to parent topicInterfaces

The concept of an interface class is purely a syntactic assist when you are defining an application class which is totally composed of abstract methods and properties. In this case by simply specify the keyword interface you are indicating that all the methods and properties are abstract. The following two definitions are semantically equivalent.

class MyInterface method MyMethod1() abstract; method MyMethod2() Returns string abstract; property string myproperty1 abstract readonly; property number myproperty2 abstract; property number myproperty3 abstract; end-class; Interface MyInterface method MyMethod1(); method MyMethod2() Returns string; property string myproperty1 readonly; property number myproperty2; property number myproperty3; end-class;

When you provide an implementation for an Interface you can also use the keyword Implements instead of Extends. While this is not mandatory, specifying Implements describes more accurately what your application class is doing.

If your class implements an interface, you don't need to create a super object interface since the system does that automatically for you.

In addition if your constructor takes no parameters and simply exists to assign to the created instance to %super (that is, there is only one statement such as %Super = create mySuper(); then you don't need to use a constructor at all.

Click to jump to top of pageClick to jump to parent topicConstructors

The constructor for a class is the public method with the same name as the (short name of the) class. The statements contained in this method (if any) provide the initialization of the class.

This constructor is always executed when an object of the class is instantiated.

Note. Before a constructor runs, the instance variables for the class are set by default based on their declared types.

Instantiate new objects of an application class by using the Create function. This function takes the name of the class, and any parameters needed for the constructor method.

If the short class name is unambiguous, that is, only one class by that short name has been imported, you can use just the short class name.

The following code instantiates an object of the class Fruit:

&Fref = Create Fruit();

If there's a possibility that the name is ambiguous, you can use the full class name to instantiate the object.

The following code instantiates an object of the Invoice class:

&InvObj = Create pt:examples:Invoice();

If the Create function is used in the context of further object expressions, that is, with a reference to members by a dot operation, the function call must be enclosed in parentheses. This is to emphasize that the creation happens before the member reference. For example:

&InvCust = (Create Invoice()).Cust();

If necessary, the constructor is supplied its parameters by the call-list after the class name in the create statement. For example:

&Example = create Example(&ConstructorParameter1, 2, "Third");

A class that does not extend some other class does not need any constructor.

A class that extends another class must have a constructor, and in the constructor, it must initialize its super class. This restriction is relaxed if the super class constructor takes no parameters, and all the constructor does is assign it to %Super. In this case, the runtime creates the super object and runs its constructor automatically. The benefit of this is two-fold: at design time you do not need to provide a constructor since the runtime automatically does the equivalent of %Super = Create MySuperObject(); Also, at runtime, you may notice a performance increase since the super class object creation and construction are done without any PeopleCode. This latter benefit can be compounded in the case where there are multiple levels of inheritance.

To the general case, to initialize a superobject, an instance of the superclass is assigned to the keyword %Super in the constructor for the subclass. This assignment is allowed only in the constructor for the subclass.

The following example shows this type of assignment:

class Example extends ExampleBase method Example(); ... end-class; Global string &CurrentBaseString; method Example ​%Super = create ExampleBase(); ​&BaseString = &CurrentBaseString; &SlashString = &BaseString; &ImportantDate = Date(19970322); end-method

If your subclass’ constructor only exists to create the superclass object and assign that to your %Super, you can dispense with providing a constructor completely as the following example illustrates.

class A ... end-class; Class B extends A ... end-class; Class C extends B ... end-class; ... Local C &c = Create C(); ...

Classes A, B and C have no constructors and the one call to Create C creates objects of class C, B and A and run their constructors. PeopleSoft recommends that unless your constructors take parameters and need to do more than be assigned to their %Super, that you do not provide constructors since that simplifies design time as well as may improve runtime performance significantly.

The above example is semantically equivalent to the following, except that it may run much faster, since it does not have to run PeopleCode at each step of the construction process.

class A ... end-class; Class B extends A Method B(); ... end-class; method B %Super = Create A(); end-method; Class C extends B Method C(); ... end-class; method C %Super = Create B(); end-method;

Note. Application classes don't have destructors, that is, a method called just before an object is destroyed. The PeopleCode runtime environment generally cleans up any held resources, so they're not as necessary as they are in other languages.

See Also

Superclass Reference

Click to jump to top of pageClick to jump to parent topicExternal Function Declarations

External function declarations are allowed in application classes, in the global and component variable declarations, after the class declaration (after the end-class statement), and before the method definitions. For example:

import SP:Record; class Person extends SP:Record method Person(&pid As string); method getPerson() Returns Record; method getUserName() Returns string; private instance Record &recPerson; end-class; ​Declare Function getUserName PeopleCode FUNCLIB_PP.STRING_FUNCTIONS FieldFormula; ​method Person /+ &pid as String +/ %Super = create SP:Record(Record.SPB_PERSON_TBL); &recPerson = %Super.getRecord(); &recPerson.PERSON_ID.Value = &pid; end-method; method getPerson /+ Returns Record +/ Return &recPerson; end-method; method getUserName /+ Returns String +/ Local string &formattedName; &formattedName = getUserName(&recPerson.PERSON_ID); Return &formattedName; end-method;

When application class properties and instance variables are used as the argument to functions or methods, they are always passed by value, never by reference. This means that the called function or method cannot change the value of the property or instance variable. If you want a function call to change a property or instance variable, use a local variable in the call and then assign the property or instance variable after the call.

Suppose you have the following class and you want to call Meth2 in the body of Meth1, passing it MyProp:

class MyClass property number MyProp; method Meth1(); method Meth2(&i as number out); end-class;

The following PeopleCode fails with a compile-time error:

method Meth1 Meth2(%This.MyProp); /* error - field or temp name required. */ Meth2(&MyProp); /* error - field or temp name required. */ end-method;

The following PeopleCode is valid:

method Meth1 /* Assignment needed if &i is input as well as output in Meth2. */ local number &Var = %This.MyProp; Meth2(&Var); %This.MyProp = &Var; end-method;

Note. You call a Java program from an Application Class the same way you do using any other PeopleCode program, that is, by using one of the existing Java class built-in functions.

See From Java to PeopleCode.

Click to jump to parent topicNaming Standards

This section describes the naming standards for:

Click to jump to top of pageClick to jump to parent topicNaming Packages

The naming standard for application packages is in the following format.

CC_XXX[_YYY]

Where CC is the company name (for example, PS is PeopleSoft), XXX is the product line, and YYY is the product code.

Examples are PS_CRM and PS_CRM_RB.

Click to jump to top of pageClick to jump to parent topicNaming Classes

Use a constructor to be the same name as the short name for the class. PeopleSoft recommends that you do not name classes to be GetXxx.

Click to jump to top of pageClick to jump to parent topicNaming Methods

Make method names simple verb or verb object words, spelled out, first letter of each word capitalized. Examples: GetField, Save, SetDefault, WriteRecord

Click to jump to top of pageClick to jump to parent topicNaming Properties

Make property names nouns, likewise spelled out, first letter of each word capitalized. Examples: Dimension, HTTPMethod, PathInfo, SubscriptionProcessId.

For Boolean read-only properties, sometimes IsXxx is appropriate. Examples: IsOpen, IsNewFieldID, IsChanged, IsDeleted

State Boolean properties positively, that is, IsChanged, as opposed to negatively, IsUnChanged. This avoids double negatives when testing (If Not &MyField.IsUnChanged Then. . . .)

Click to jump to parent topicImport Declarations

Before you can use a class name in a PeopleCode program (either a class definition program or an ordinary PeopleCode program), you must first import it using an import statement at the beginning of your program.

An import statement names either all the classes in a package or one particular application class.

If you're importing all the classes in a package, the syntax for the import statement ends with the following:

:*

This makes all the application classes directly contained in the named package available. Application classes contained in subpackages of the named package are not made available.

If you're importing one particular application class, the syntax of the import statement ends with the short name of the class. Only that class is made available.

For example, the following imports all the classes of the package named Fruit:

Import Fruit:*;

The following imports only the application classes Banana and Kiwi. If the package named Fruit contains other classes, those are not made available to the PeopleCode program:

Import Fruit:Banana; Import Fruit:Kiwi;

If you had a subpackage in Fruit named Drinks, you could access all the classes in that subpackage like this:

Import Fruit:Drinks:*;

A PeopleCode program (either a separate program or one contained within a class definition) can use only application class names that have been imported. However, a class definition can use its own name without having to import it.

It's possible to import two packages which contain application classes with the same short name. For example, suppose my package Fruit contained classes Apple and Banana. Suppose a second package, Drinks, contained Apple and Cherry.

Import Fruit:*; Import Drinks:*;

You could refer to the Banana and Cherry classes using just the short name of the class. However, you couldn't refer to the Apple class by the short name. You must always use the full name reference (that is, the name of the package and the name of the class) when referring to Apple.

Global Banana &MyBanana; Local Cherry &CherryTree; Component Fruit:Apple &GreenApple;

The following line produces an error, because the program doesn't know which Apple class you're referring to:

Component Apple &GreenApple;

Note. Single class imports (such as, Import Fruit:Banana) are checked for existence when you save your PeopleCode.

Click to jump to parent topicSelf-Reference

A method can refer to the current object using the %This system variable.

Due to subtyping, %This is an object of either the method's class or a subclass of the method's class.

In PeopleCode, the methods and properties of the class cannot be used without an object qualification.

In the following code example, the line in bold indicates an error. You can't call the class this way: you must use %This.

class FactorialClass method factorial(&I as number) returns number; end-class; method factorial if &I <= 1 then return 1; end-if; ​return &I * factorial(&I - 1); /* error - factorial undefined */ ​return &I * %This.factorial(&I - 1); /* okay */ end-method;

One of the implications of this is that when you're writing a method, there isn't any way to guarantee you'll access your own class' version of a public method (rather then a subclass') as it might be overridden by a subclass. The only way to make sure that you can access your own method is to make it private.

If you have some action that you also want to make public, and you want guaranteed access to it, you can make the action a private method, then define a public method for it that calls the private one.

In the following example, factorial is the public method that can be used by other classes. myFactorial is the private action.

class FactorialClass method factorial(&I as number) returns number; private method myFactorial(&I as number) returns number; end-class; method factorial return myFactorial(&I); end-method; method myFactorial if &I <= 1 then return 1; end-if; return &I * %This.myFactorial(&I - 1); end-method;

If you declare an instance variable as private you can still access it as a private property in another instance of the same class. For example, given the following declaration:

class Example private instance number &Num; end-class;

A method of Example could reference another Example instance's &Num instance variable as follows:

&X = &SomeOtherExample.Num;

Click to jump to top of pageClick to jump to parent topicUsing %This with Constructors

%This when used in application class constructor code refers to the object currently being constructed. It does not refer to the dynamic this pointer of some object under construction. Given these two application classes, the PeopleCode %This.Test() in the Base constructor always refers to the Test method in the Base class.

class Base method Base(); method Test(); method CallTest(); property string sTestResult; end-class; method Base %This.Test(); end-method; method Test &sTestResult = "BASE_METHOD_CALLED"; end-method; method CallTest %This.Test(); end-method; import PACKAGE:Base; class Extend extends PACKAGE:Base; method Extend(); method Test(); end-class; method Extend %Super = create PACKAGE:Base(); end-method; method Test /+ Extends/implements PACKAGE:Base.Test +/ %This.sTestResult = "EXTENSION_METHOD_CALLED"; end-method;

Even though the Extend class method provides its own Test method which overrides Base's Test method, in PeopleCode create Extend() which ultimately runs Base's constructor, the %This.Test() call in Base's constructor still references Base's Test method, not Extend's Test method, because %This always refers to the object under construction

Click to jump to parent topicProperties and Constants

This section discusses the following ways to use properties and constants with application classes:

Click to jump to top of pageClick to jump to parent topicDifferentiating Between Properties and Methods

A method is a procedure or routine, associated with one or more classes, that acts on an object.

A property is an attribute of an object.

PeopleSoft recommends that you use read-write or read-only properties instead of creating methods named GetXxx and SetXxx. For example, instead of creating a method GetName, that takes no parameter, just to return the name of an object, create a read-only property Name.

If your properties simply set or return the value of an instance variable, it is far more efficient to declare the property that way than have a get and set method. The overhead of having a get and set method means that each time the property is reference some PeopleCode has to be run.

Application classes can have read-only properties, but no indexed properties.

Considerations Creating Public Properties

There are two implementations of (public) properties:

From outside the class, you cannot tell the difference between them (for example, both are dynamically bound). However, if you just want to expose an instance variable to users of the class, you can declare a property of that name and type, which declares the instance variable too:

class xxx property string StringProp; end-class

If you want the property to be read-only outside the class, use the following code:

class xxx property string StringProp readonly; end-class

Both of these code examples declare an instance variable called &StringProp and provide its value for getting and change its value for setting (if not readonly). You can think of this as shorthand for the usual implementation of get-set methods.

If you want to implement the same with code (perhaps deriving the property from other instance variables or other data), use the following sort of PeopleCode program:

class xxx property string StringProp get set; end-class; get StringProp return "string"; /* Get the value from somewhere. */ end-get; set StringProp /* Do something with &NewValue. */ end-set;

To specify a read-only property, omit the set portions of the code example.

Click to jump to top of pageClick to jump to parent topicOverriding Properties

A property of a superclass can be overridden by a subclass by providing a different implementation.

The properties of a class are implemented by the keywords Get and Set, or by access to an otherwise private instance variable.

To access the property, you do not have to specify Get or Set: the context tells the processor which task you're doing. To create read-only properties, specify only a Get method, with no Set method, or for instance variable properties, specify Readonly.

For an instance variable property, there are two different ways for method code in the class itself to refer to the property:

The first way is dynamically bound, as it uses whatever (possibly overridden by a subclass) implementation of PropertyName that the current object provides.

The second way always accesses the private instance variable of the class that the method is declared in.

The following example returns strings, by converting the property. It also demonstrates overriding.

class A property number Anum; property string Astring ​get; property string Astring2 ​get; end-class; /* The following is a dynamic reference to the Anum property of the current⇒ object, which might be a subclass of A, so this might not access the A⇒ class&rsquo; implementation of Anum as an instance variable. */ ​Get Astring ​return String(%This.Anum); ​end-get; ​/* The following is a static reference to our &Anum instance variable. Since it⇒ does not use %This, it will not be overridden even if the current object is a⇒ subclass of A. */ ​Get Astring2 ​return String(&Anum); ​end-get; ​/* The following overrides the Anum property of our superclass, in this case by providing another instance variable implementation. This gives us our own &Anum instance variable. */ class B extends A property number Anum; end-class; . . . /* Set the Anum property in B. Because of the above definitions, this sets the &Anum instance variable in the B object, but not the &Anum instance variable in its superobject. In the absence of other setting, the latter will be defaulted to 0. */ local B &B = Create B(); &B.Anum = 2; &MyValue = &B.Astring; /* &MyValue is "2" */ &MyValue = &B.Astring2; /* &MyValue is now "0" */

Click to jump to top of pageClick to jump to parent topicUsing Get and Set with Properties

PeopleSoft recommends against using read-only properties that are public and mutable in application classes (similar to public instance variables) because this allows external code to read and change the internal state of the object without any controls. Instead, modify the property declarations with the Get and Set keywords.

There is a slight performance advantage, and you write less code, if you use the Get and Set keywords over using get and set methods.

If you define a property with the Get and Set keywords, you also must define a get or set block in the same part of the code that contains the method bodies.

Click to jump to top of pageClick to jump to parent topicUsing Read-Only Properties

PeopleCode read-only properties are functionally similar to static variables, as long as the class that defines the properties initializes them and does not change them. The difference is that you need an instance of the class to access them.

For example, consider a Category object that has a CategoryType member that can have one of the following values:

You can define three read-only properties corresponding to each of these values, REGULAR, BROWSE, and NEWS, then initialize them to the appropriate values in the constructor of the class.

When you write code to evaluate the CategoryType of the Category object, perform a test like this:

If (&category.getCategoryType() = &constants.NEWS) then...

PeopleSoft recommends referring to the read-only properties, rather than their literal values, for the following reasons:

Click to jump to top of pageClick to jump to parent topicUsing Methods and Properties for Collections

Application classes can contain collections. Collections of objects generally have at least the following methods and properties.

All numeric indexes in PeopleCode are one-origin, that is, start all indexes at 1, not 0.

Click to jump to top of pageClick to jump to parent topicDeclaring Constants

PeopleSoft recommends that if constants are inextricably linked to a class, you should define them within that class. If the constants are more general, potentially used by multiple classes, consolidate the constants into a constants class at application-level or package-level.

Message catalog set and message numbers are good candidates to centralize into a single constants class. It can improve the readability of code and make it easier to maintain these values.

For example, you can define a constant MSG_SET_NBR, and then define constant values for each message that explain a little about what the message represents (like REQUIRED_VALUE_MISSING, UNIMPLEMENTED_METHOD, or INSUFFICIENT_PRIVILEGES).

Click to jump to parent topicUsing Variables in Application Classes

This section discusses how to use the following variables in application classes:

Click to jump to top of pageClick to jump to parent topicPlacement of Variable Declarations

Variables are declared after the class definition (the end-class statement) before anything else. After you have declared a variable, you can use it anywhere in your program.

class Example method Example_M1(&par As string); end-class; ​Global boolean &b; ​ method Example_M1 /+ &par as String +/ &b = False; end-method;

Click to jump to top of pageClick to jump to parent topicDeclaring Private Instance Variables

A private instance variable is private to the class, not just to the object instance. For example, consider a linked-list class where one instance needs to update the pointer in another instance. Another example is the following class declaration:

class Example private instance number &Num; end-class;

A method of Example could reference another instance of the Example &Num instance variable as:

&X = &SomeOtherExample.Num;

Avoid making every instance-scoped variable a public property. You should consider each variable individually and decide if it belongs in the public interface or not. If it does, decide if the variable warrants get or set modifiers and therefore should be a public property. If the variable only serves internal purposes to the class, it should be declared as a private instance variable.

Click to jump to top of pageClick to jump to parent topicGlobal Variables

PeopleSoft recommends avoiding global variables in application classes unless there is a situation where no other code works. Generally, an application class should not know about anything scoped outside of its instance. There are exceptions, since not all application classes should be standalone. For example, an application class that interacts with the Component Buffer must know about the Component Buffer objects.

Click to jump to top of pageClick to jump to parent topicOverriding Variables and Properties

PeopleSoft recommends against overriding of variables and of properties.

Since instance variables are private in scope, you cannot access them in subclasses, but you can redeclare them in subclasses. The same is true of public properties; you can even explicitly access the overridden or overriding property. However, overriding is not recommended.

Click to jump to parent topicSuperclass Reference

A method can refer to a member of its superclass by using the %Super system variable. This construction is needed only to access superclass members that are hidden by overriding members in the current class.

In the following example, the classes that extend the general BuildingAsset class each have their own method DisasterPrep, that does the specific processing, then calls the superclass (generic) version of DisasterPrep.

/* generic building class */ class ​BuildingAsset ​method Acquire(); method DisasterPrep(); end-class; method Acquire %This.DisasterPrep(); end-method; ​method DisasterPrep PrepareForFire(); end-method; ​/* building in Vancouver */ class VancouverBuilding extends BuildingAsset ​method DisasterPrep(); ​end-class; method DisasterPrep PrepareForEarthquake(); ​%Super.DisasterPrep(); /* call superclass method */ end-method; /* building in Edmonton */ class EdmontonBuilding extends BuildingAsset ​method DisasterPrep(); ​end-class; method DisasterPrep PrepareForFreezing(); ​%Super.DisasterPrep(); /* call superclass method */ end-method; local BuildingAsset &Building = Create VancouverBuilding(); &Building.Acquire(); /* calls PrepareForEarthquake then PrepareForFire */ &Building = Create EdmontonBuilding(); &Building.Acquire(); /* calls PrepareForFreezing then PrepareForFire */

Click to jump to parent topicDowncasting

Downcasting is the process of determining if an object is of a particular subclass type. If the object has that subtype (either the object is of that subtype, or is a subtype of it), a reference to the subobject is returned, otherwise Null is returned. In either case, the type of the resulting value is compatible with the named subclass type.

This downcast inquiry into the actual type of an object can be used when the object has been passed to some general facility, then passed back to more specific code. For example, the general facility might be a dispatch mechanism, or a new storage structure such as a binary balanced tree. These general facilities won't know about specific types, but it might be necessary for the specific program using the general facility to recover the actual type of an object that is returned to it by the general facility.

A downcast should not be used when you could add members to a common base class to provide the same functionality. In other words, if you find yourself using the downcast to test whether the object is one or another of several related types, you should add members to the common base class to provide the operations or properties that you are trying to access, then provide separate implementations of those actions or properties in each specific class.

If the downcast operator is to be used in the context of further object expressions (such as references to other members using dot notation) then the downcast must be enclosed in parentheses to emphasize that the downcast happens before the member reference.

class Fruit property number FruitCount; end-class; class Banana extends Fruit property number BananaCount; end-class;

In the following code example, first the variables are assigned. All the variable assignments are legal, for Banana is a subtype of Fruit.

local Banana &MyBanana = Create Banana(); local Fruit &MyFruit = &MyBanana; /* okay, Banana is a subtype of Fruit */ local number &Num = &MyBanana.BananaCount;

The next two lines of code don't produce an error, as &MyFruit is currently a Banana at runtime.

&MyBanana = &MyFruit as Banana; &Num = (&MyFruit as Banana).BananaCount; /* same as &MyBanana.BananaCount */

In the next lines of code, we're reassigning &MyFruit to be of type Fruit, that is, of the superclass Fruit. When you try to reassign &MyFruit as Banana, &MyBanana is assigned as Null, because &MyFruit is no longer of type Banana.

&MyFruit = Create Fruit(); &MyBanana = &MyFruit as Banana; /* assigns Null - &MyFruit isn't a Banana */

Click to jump to parent topicException Handling

Use the Exception class to do exception handling in your PeopleCode. This class provides a try, catch, and throw mechanism so you don't need to check after each operation for errors. Instead, by the structure of the try-catch blocks, you can declare when you are interested in handling exceptions, and how you want to handle them.

Exceptions are instances or subclasses of the PeopleCode Exception class. Oracle recommends that when applicable, application class methods should throw exceptions instead of communicating back to the calling code with return values. You can create exceptions by:

Since a method can throw exceptions for several different reasons, Oracle recommends that you:

This allows the calling code to make decisions based on the exception type.

For example, a method that retrieves customer data from a database might throw an exception named SQLException if a database error occurs, or an exception named PrivilegeException if the current user doesn’t have the appropriate permissions to perform the operation. There could be different errors causing either of these exception types to be thrown in this method; if necessary, you can write the calling code to examine the specific message numbers and react accordingly.

Oracle recommends that you always catch an exception; if it is not caught, it causes a runtime error. Use a try-catch block.

Not catching an exception causes a runtime error and can cause PeopleTools to display a dialog box with the message catalog entry and information about the technical context of the exception. The reasons for avoiding this by using try-catch blocks are:

See Also

Exception Class

CreateException

throw

try

Click to jump to parent topicCommenting and Documenting Application Classes

This section contains guidelines for writing method header comments, class header comments, and tags inside the comments. It discusses:

Click to jump to top of pageClick to jump to parent topicUnderstanding Comments and Documentation

Documentation is important in all code, but even more so in application class code, which aims at, and incurs certain overhead in the name of, higher levels of reuse.

There are two types of inline comments:

Warning! In application classes you will see the use of /+ +/ style comments. Do not use these in your PeopleCode. These annotations are generated by the compiler. If you use them, they will be removed the next time you validate, compile, or save your PeopleCode. They are used to provide signature information on application class methods and properties, and are regenerated each time the compiler compiles your application class PeopleCode. Instead, use the standard commenting mechanisms listed above.

PeopleSoft recommends keeping a running line of asterisks along one side of an extensive comment to help the readability of the code by making the entire comment stand out from the surrounding code.

Click to jump to top of pageClick to jump to parent topicMethod Header Comments

The following is an example of documentation conventions for method header comments, which are also suitable for PeopleCode. It contains comment tags, which are explained below the example.

/** * Description of what method does * * @param a optional description of param a * @param b optional descriptions of param b * @exception PrivilegeException thrown if etc, etc * @exception SQLException thrown if etc., etc. * @return String - description of potential values */ Method myMethod ... End-method;

Method Comment Tags

The following are the suggested tags for commenting methods.

Tag

Description

@param N

Specify a description for each method parameter. The name of the parameter is specified after the keyword @param.

@exception name

Specify a description of each exception class. The name of the exception is specified after the keyword @exception. For example, the descriptions can explain what causes certain exceptions to be thrown.

@return Type

Specify a description of the return value. The type of data that is returned is specified after the keyword @return. For example, explain the potential values a method may return, whether it returns null in some circumstances, and so on.

Not all methods require documentation. For example, some simple set or get methods have method signatures that are descriptive enough. In other cases, it may suffice to include a brief sentence in the header explaining what the method does.

As with methods, PeopleCode get or set blocks should also carry method header comments.

Click to jump to top of pageClick to jump to parent topicClass Header Comments

Header comments for the class should provide descriptive information about the class, and may optionally include additional tags, indicating version and author:

/** * class description * * @version 1.0 * @author amachado */

Class Header Comment Tags

The following are the suggested tags for commenting class headers.

Tag

Description

@version number

Specify a version number for a class.

@author name

Specify an author for a class.

Click to jump to parent topicDesigning Base Classes

This section discusses some ways you can design application classes.

Click to jump to top of pageClick to jump to parent topicBase Classes

Base classes contain a representation of data elements, such as documents, categories, users, and miscellaneous security-related entities.

To design the document data element to be integration-friendly, PeopleSoft recommends you start with a relatively basic base class. Then use more specialized types of documents to create a subclass from that base class, adding the necessary specialized attributes.

Even if you think of ways to use data to drive the business rules, PeopleSoft recommends that you do not place them into your data objects. Replicating business rules for every instance of a data element can be detrimental to performance.

Click to jump to top of pageClick to jump to parent topicAbstract Base Classes

Abstract base classes contain reusable logic for PeopleCode classes; you do not instantiate them directly. Instead, you instantiate classes that are subclasses of the abstract base class. Abstract base classes use placeholder methods for specialized logic, and its subclasses override those methods to provide the specialized logic.

An example of a candidate for an abstract base class is a class that is used for administering a data entity, such as an invoice. Such a class has a Save method. A Save method can use normal methods to call generic validation routines, talk to the database, and handle errors; it can use the placeholder methods for specialized logic, such as mapping a given data class to a particular database table.

PeopleSoft recommends that you program an active validation check into your placeholder method that causes a runtime error, such as throwing an UnimplementedMethodException, if an abstract base class placeholder method hasn’t been overridden.

Click to jump to top of pageClick to jump to parent topicGeneric Base Classes

Generic base classes contain reusable logic for PeopleCode classes; you write them to be self-contained, fully implemented, and capable of being instantiated directly. This differs from abstract base classes, which are not instantiated directly and need subclasses that override methods to provide specialized logic.

Some examples of classes that are good candidates for creating generic base classes are:

Even when a class does not seem generic because it only has a couple of subclasses, you can still define it in your design as a generic base class rather than cloning common code across different classes. The main reason is maintainability: it's easier to maintain a single class than trying to keep track of the same code scattered across your database.

Click to jump to top of pageClick to jump to parent topicUtility Classes

Some reusable code is the kind you typically don’t want to inherit, but you just want to use here and there. Utility classes can serve this purpose.

String parsing, data type conversion, and formatting routines are all good candidates for utility classes. PeopleSoft recommends that anytime you code something that’s more than just a line or two, and that seems to be reusable, write it as a utility class.

Click to jump to parent topicDeclaration of Application Classes

This section discusses instructions for declaring application classes, such as:

Click to jump to top of pageClick to jump to parent topicDeclaring Application Classes

Application object references are declared in your PeopleCode programs by either the short name of the class (if the short name is unambiguous amongst all the imported classes), or by the full name of the class. Like all uses of class names, to use the name in a variable declaration, you must have imported the class. Application objects can be of Local, Global, or Component scope.

Every application class is a definition of a new data type in PeopleCode, like the record, rowset, or field data types. The application class includes both the definition of its external interface, its data (properties and instance variables), and its actions (methods), just like the PeopleSoft delivered classes.

Click to jump to top of pageClick to jump to parent topicImporting Class Names

When you import a class name, fully-qualifying it is optional. The syntax is:

<package>:<subpackage>:<...>:<classname or wildcard>

PeopleSoft recommends that you individually import each class when you import multiple classes from the same package, instead of using wildcards.

Click to jump to top of pageClick to jump to parent topicReferencing Superclasses

PeopleSoft recommends that you do not set %Super to a new instance of the current class you are defining because this would start an infinite loop.

/* Do not do this! */ %Super = %This;

Click to jump to top of pageClick to jump to parent topicDeclaring Private Methods

PeopleSoft recommends that you use private methods for succinct operations, even if they aren’t reused, to improve the readability and maintainability of the code. You can also do this by using many inline comments.

Click to jump to parent topicScope of an Application Class

Application classes can be instantiated only from PeopleCode. These classes can be used anywhere you have PeopleCode, that is, in message notifcation PeopleCode, Component Interface PeopleCode, record field PeopleCode, and so on.

Click to jump to parent topicApplication Classes Built-in Functions and Language Constructs

In this section, we discuss the Application classes built-in functions and language constructs, in alphabetical order.

Click to jump to top of pageClick to jump to parent topicClass

Syntax

Class classname [{Extends | Implements} Classname] [Method_declarations] [Property_declarations] [Protected [Method_declarations] [Instance_declarations] [Constant_declaration]] [Private [Method_declarations] [Instance_declarations] [Constant_declaration]] End-Class

Where Method_declarations are of the form:

Method methodname([MethodParam1 [, MethodParam2. . .] [Returns Datatype]] [abstract])

Where Property_declarations are of the form:

Property DataType PropertyName {{[Get] | [Set]} | [abstract] | [readonly]}

Where Instance_declarations are of the form:

Instance DataType &Variable1 [, &Variable2. . .]

Where Constant_declarations are of the form:

Constant &Constant = {Number | String | True | False | Null }

Description

Use the Class language construct to build application classes in an application package. All classes within a package must be uniquely named, however, classes contained in different packages do not have to be named uniquely.

External function declarations are allowed in application classes, in the global and component variable declarations, after the class declaration (after the end-class statement), and before the method definitions.

Parameters

classname

Specify the name of the class that you are creating. All classes within a package must be uniquely named, however, classes contained in different packages do not have to be named uniquely.

Extends | Implements classname

For a regular class, specify the name of the class that this class extends. If the class is an interface type of class, specify the name of the interface that this class implements.

You must import the class to extend it.

Method_declarations

Specify the methods (and their signature) as used in this class.

Property_declarations

Specify the properties, and their usage, in this class.

Protected

Use this keyword to declare any methods, constants, or instance variables as protected to the class, that is, are only visible to the declaring class and subclasses.

Private

Use this keyword to declare any methods, constants, or instance variables as private to the class, that is, they can't be accessed by any other classes.

Instance_declarations

Specify any variables that should be in any instance (object) of the class.

Constant_declarations

Specify any constants that should be used with this class.

Returns

None.

Example

class Example extends ExampleBase method NumToStr(&Num as number) returns string; method AppendSlash(); property number SlashCount get; property number ImportantDayOfWeek get set; property string SlashString readonly; property date ImportantDate; private method NextDayOfWeek(&DoW as number) returns date; constant &Sunday = 1; instance number &BaseString; end-class;

See Also

Method, Get, Set.

Click to jump to top of pageClick to jump to parent topicGet

Syntax

Get PropertyName StatementList End-Get

Description

Use the Get language construct when defining properties in an application class that are implemented by methods rather than an instance variable. All properties within an application class must be uniquely named.

Parameters

Get PropertyName

Specify the name of the property that you're implementing.

StatementList

Returns the value of the property. In other words, this is a method which has no parameters and must return the value of the property.

Returns

Depends on the assignment within StatementList

Example

Get FruitCount Return &MyFruit.Number(); End-Get;

See Also

Method, Set.

Return

Click to jump to top of pageClick to jump to parent topicImport

Syntax

Import PackageName:[PackageName. . .:]{Classname | *}

Description

Before you can use a class name, you must first import it using an import declaration statement at the beginning of your program.

An import declaration statement names either all the classes in a package or a single application class.

Parameters

Import PackageName

Specify the name of the package that you want to import.

*

Import all the classes of the specified package.

Classname

Import only this class of the specified package. You won't have access to any other classes in the specified package, only this one.

Returns

None.

Example

The following gives you access to all the classes in the package Fruit:

Import Fruit:*;

The following only gives you access to the class Banana in the package Fruit:

Import Fruit:Banana;

The following gives you access to the class Apple, in the package Drinks, which contains the package Fruit:

Import Drinks:Fruit:Apple;

See Also

Class.

Click to jump to top of pageClick to jump to parent topicInterface

Syntax

Interface classname [{Extends | Implements} Classname] [Method_declarations] [Property_declarations] [Protected [Method_declarations] [Instance_declarations] [Constant_declaration]] ] End-Interface

Where Method_declarations are of the form:

Method methodname([MethodParam1 [, MethodParam2. . .] [Returns Datatype]] [abstract])

Where Property_declarations are of the form:

Property DataType PropertyName {{[Get] | [Set]} | [abstract] | [readonly]}

Where Instance_declarations are of the form:

Instance DataType &Variable1 [, &Variable2. . .]

Where Constant_declarations are of the form:

Constant &Constant = {Number | String | True | False | Null }

Description

Use the Interface language construct to create classes of type interface in an application package. An interface class is a purely abstract class.

Parameters

An interface does not have Private methods or properties, but all the other parameters are identical to the Class language construct.

See Class.

Returns

None.

See Also

Class

Click to jump to top of pageClick to jump to parent topicMethod

Syntax

Method MethodName StatementList End-Method

Description

Use the Method statement to define the methods of your application class.

Parameters

Method methodname

Specify the name of the method that you are creating.

StatementList

Specify the program of the method, what it does.

Returns

Depends on the method.

Example

method NumToStr return String(&Num); end-method; method AppendSlash &SlashString = &SlashString | "/"; end-method;

See Also

Get, Set.

Return

Click to jump to top of pageClick to jump to parent topicSet

Syntax

SetPropertyName StatementList End-Set

Description

Use the Set language construct when implementing properties in an application class. All properties within an application class must be uniquely named. The new value for the property is available in the &NewValue parameter of the Set method.

Note. You cannot create a set-only property. You can create only get-set properties.

Parameters

Set PropertyName

Specify the name of the property that you're implementing.

StatementList

Change the value of the property to be &NewValue.

Returns

None.

Example

Set FruitCount &Fruitcount = &MyFruit[&NewValue].ActiveRowCount(); End-Set;

See Also

Get, Method.