This section describes the declaration statements (or declarative statements) for
◈ data types and data objects, the statements for defining
◈ classes and interfaces as well as their components, the statement for declaring
◈ field symbols
The statements PARAMETERS and SELECT OPTIONS for declaring input fields in selection screens are also declarative statements, but are executed separately in the respective sections.
Note
Alongside the explicit ways of declaring data objects described here, there are also statements and additions that declare data objects implicitly, such as SELECTION-SCREEN COMMENT. However, most of these statements are obsolete
1.1 Data Types and Data Objects
This section describes the declaration of data types and data objects.
Data Types
Data types are templates for creating data objects. Data types can be defined independently in the ABAP program or in ABAP Dictionary. As attributes of a data object, data types can also exist in a non-independent state. Data types do not use any memory space for work data, but may require memory for administration information.
Data objects
A data object is an instance of a data type and occupies as much memory space as its type specifies. An ABAP program only works with data that is available as content of data objects. Data objects are either created implicitly as named data objects, or explicitly as anonymous data objects using CREATE DATA.
Data types of data objects
Data objects can be declared by reference to a non-generic data type of the same ABAP program or from ABAP Dictionary. In this case, the data type determines the complete technical attributes of the data object. A data object can also be constructed in the ABAP program without completely specified type definitions. The data type of a data object of this type is always complete, and does not exist independently, but rather as an attribute of the data object, and is called a bound data type.
Note
The data types of all class attributes belong to the static class properties. A LIKE addition enables you to refer to the visible class attributes without first creating an object by using the class component selector or reference variables
Declaration statements
◉ Declaring Data Types
◉ Declaring Data Objects
1.1.1 Types and Objects - Overview
In ABAP, we distinguish between types and objects. Types are purely descriptions, to which no data memory is attached apart from administration information. Objects are instances of types and take up memory space. A type characterizes the technical properties of all objects of the relevant type.
The ABAP types form the ABAP type hierarchy, which is illustrated below:
The left side of the graphic shows the hierarchy of all types and instances, for instance which types are possible in ABAP and the objects that can be generated from these types. The right side lists the generic data types assigned to individual nodes of the type hierarchy.
In principle, we distinguish between data types and object types.
◈ Data types are used to describe data objects. They are further subdivided into elementary types, reference types, and complex types. Data types are predefined or they can be defined locally in the program and system-wide in ABAP Dictionary. Data objects as instances of data types are fields in their own right. They contain local program data that a program uses at runtime.
◈ Object types are used to describe objects in ABAP Objects. They are divided into classes and interfaces. Object types contain the above data types, but they also contain functions. Object types are not predefined and must be defined in the program or in the Class Library. Classes provide a complete description of an object. They define which data types and which functions an object contains. Interfaces describe one aspect of an object. The data types and functions of an interface can be implemented by more than one class. Objects as instances of classes are actual software objects in ABAP Objects. They support object-oriented programming by containing methods and events in addition to data.
The following sections summarize some important facts on data types and data objects.
◆ Data Types
Data types are a subtree of the ABAP type hierarchy. Data types are only type descriptions. Data types do not have any attached memory for storing working data, but they may require space for administration information. A data type characterizes the technical attributes of all data objects that have this type. In ABAP, data objects occur as attributes of data objects, but they can also be defined as stand-alone data types.
The definition of stand-alone data types is based on a set of predefined data types. Stand-alone data types can either be defined internally in the program using the statement TYPES in the global declaration part of a program, in the declaration part of a class, locally in procedures, or for all programs in the ABAP Dictionary. Data types in ABAP Dictionary are either created directly as repository objects or in a type group.
Predefined and self-defined data types can be used to create data objects and for typing. For the latter in particular, predefined generic data types are available. A generic data type is a data type that does not determine all attributes of a data object. Generic data types can only be used for typing formal parameters and field symbols.
Data types can be divided into elementary, reference, and complex types.
- Elementary types are 'atomic' in the sense that they are not composed of other types. They are further classified into elementary types of fixed length and of variable length.
- There are 13 predefined elementary data types of fixed length in ABAP. There are eight numeric types: Integers (b, s, i, int8), decimal floating point numbers (decfloat16, decfloat34) binary floating point numbers (f) and packed numbers (p). There are two character-like types: Text fields (c) and numeric text fields (n). Byte-like type: Byte fields (x). There are two date and time types: Date fields (d) and time fields (t). The data types c, n, x, and p are generic in terms of length. p is also generic in terms of the number of fractional digits. The numeric data types b and s cannot be specified directly in programs for short integers.
- There are two predefined elementary data types of variable length in ABAP. There is one character-like type: Text string (string). Byte-like type: Byte string (xstring).
- Reference types describe data objects that contain references to other objects (data objects and instances of classes), which are known as reference variables. There are no predefined reference types in ABAP. A reference type must either be defined in the ABAP program or in ABAP Dictionary. Reference types form a hierarchy, which represents the hierarchy of the objects to which the references can point.
- Complex data types are composed of other types. They enable the administration and processing of semantically related datasets under one name. A data object of a complex type can be accessed overall or by component. With the exception of the structure sy, there are no predefined complex data types in ABAP. A complex type must either be defined in the ABAP program or in ABAP Dictionary. There are two types of complex data type:
- A structured type is a sequence of any elementary reference or complex data types. Structures are used for grouping together work areas that logically belong together.
- Table types consist of a sequence of any number of rows of the same data type. Table types are characterized by a row type, which can be any elementary data type, a reference data type, or a complex data type. They are also characterized by the table type, which defines how tables can be accessed, and by a table key, which is used to identify the table rows.
- A mesh type is a special structured type with tabular components linked using associations.
◆ Data Objects
Data objects are instances of data types and contain the concrete data that a program uses at runtime. This is done by specifying data objects in operand positions.
Creating and Addressing Data Objects
The following objects are distinguished:
◈ Named data objects, which are statically agreed with a data-defining statement and are addressed using a name. The typical data-defining statement is DATA. Named objects are created at the start of the lifetime of a context (program, class, object, procedure) by the ABAP runtime environment, and exist for as long as their context exists.
◈ Anonymous data objects, which are created by the statement CREATE DATA and are addressed using data reference variables. Anonymous data objects exist in the internal session of the program in which they were created, and are subject to garbage collection.
◈ Literals, which are defined in the source code of a program and are fully defined by their value.
In addition to data objects declared in programs, there is a set of predefined data objects, which can always be accessed in ABAP programs. In addition, some statements create data objects implicitly, which are then available for special purposes. Examples include sum( ), cnt( ) in control level processing for extracts and title when selection screens are created.
Data Types of Data Objects
Every data object has a certain data type, and every data object uses memory to store the data. The data type of a data object is defined either with reference to a standalone data type or, when the data object is created, as a bound data type.
The data type of a data object is always uniquely defined at the runtime of the program and cannot be changed. In the case of anonymous data objects, this data type determines the dynamic type of the related reference variables.
Variable and Constant Data Objects
With respect to changing data object values, variable data objects are distinguished from constant data objects. Variables can change their value at runtime. Constants always keep their initial value. Literals and text symbols are also constant. Input parameters in procedures are generally not modifiable either, if this would cause the assigned actual parameter to be changed.
Static and Dynamic Data Objects
Static data objects, for which all technical attributes need to be defined on declaration, are distinguished from dynamic data objects, whose memory requirement or size is not defined until runtime. Strings and internal tables are dynamic data objects.
After declaration, the length of a string is equal to 0 and changes at runtime depending on the content assigned to it. After declaration, internal tables do not contain any rows. Any number of rows is possible, and the rows are defined dynamically at runtime when the internal table is filled.
Structures that contain dynamic components are also dynamic data objects.
Flat and Deep Data Objects
All static data objects except reference variables are flat. Their content corresponds to the actual work data. Dynamic data objects and reference variables are deep. They contain references to the actual content. The handling of references is implicit for dynamic data objects (strings and internal tables), and explicit for reference variables.
Structures that do not contain any deep components are flat structures. Structures that contain at least one deep component are deep structures.
1. Byte Order
The byte order determines the order in which bytes of specific data objects are stored in the memory.
Binary Representation of Numbers
The binary representation of ABAP type i, int8, decfloat16, decfloat34, f, and s numbers is hardware-dependent. The byte order, which is pre-defined by the processor, is important: It determines whether the highest-value byte or lowest-value byte is stored first. In the case of the highest-value byte, the binary display is referred to as big endian and with the lowest-value byte, the display is known as little endian.
Example
The number 16909060 can be represented using the following byte sequences (in hexadecimal notation):
Endian | Byte 1 | Byte 2 | Byte 3 | Byte 4 |
Big | "0x01" | "0x02" | "0x03" | "0x04" |
Little | "0x04" | "0x03" | "0x02" | "0x01" |
The most common processors are Intel and DEC alpha, both of which use little endian. Most other processors use big endian.
Binary Representation of Characters
In the Unicode format UCS-2, supported by the ABAP programming language, characters are represented using 2-byte unsigned integer values. This means that this format depends on the number representation used by the hardware. This means that UCS-2BE (big endian) must be distinguished from UCS-2LE (little endian).
Container Problems
Character-like or byte-like data objects of the type c or string, or x or xstring are often used as anonymous containers for data objects, especially structures, and stored persistently.
If a container like this is stored and imported on an application server with a different byte order, problems can arise if the container is used for contents for which the byte order is important. This is always the case when numeric content of the type i, int8, decfloat16, decfloat34, f, or s is stored in character-like or byte-like containers. Problems can also arise when byte-like content is saved in character-like containers.
Usually, to be able to work with the contents of an imported container, a casting is executed on the data type, whose data is stored in the container. However, because no type information is stored in the container, any necessary conversion of the byte order cannot take place.
The only way to prevent these problems arising is to avoid having numeric components in anonymous containers and never store byte-like contents in character-like fields.
2. Alignment of Data Objects
Data objects with the following data types cannot simply be stored at random addresses in the main memory:
⬥ Numeric data objects of types i, int8, decfloat16, decfloat34, and f
⬥ Deep data objects
⬥ Character-like data objects
For example, an ABAP field with the type i must have an address divisible by four, a field with the type int8, f, or decfloat16 must have an address divisible by eight, and a field with the type decfloat34 must have an address divisible by 16. In the case of the character representation UCS-2 used by the ABAP programming language, the memory address of character-like data objects must be divisible by 2.
⬥ An elementary data object is aligned when it has an address that corresponds to its data type.
⬥ A structure is aligned when the following applies:
⬥ Its start address satisfies the strictest alignment requirements of its components and
⬥ The offsets of all components satisfy the same type-specific divisibility requirements.
The correct alignment of data objects is not normally an issue, because they are created correctly automatically in the declaration. This can produce alignment gaps in structures with components of different data types.
However, the alignment must be checked in the following cases:
⬥ In assignments and comparisons of structures where the structure fragment view that splits a structure into fragments in accordance with its alignment gaps must be respected.
⬥ When a data object is handled using explicit or implicit casting with another data type.
⬥ When a work area that has a different type from the database table is used in an Open SQL statement.
If a statement expects a particular alignment of a data object, an exception is raised if there is insufficient alignment.
Notes
⬥ Components that are included in structures using INCLUDE TYPE|STRUCTURE behave like genuine substructures with respect to alignment.
⬥ The binary content of alignment gaps is not defined and cannot be evaluated.
⬥ Alignment gaps can also occur at the end of structures, since the overall length of the structure is determined by the component with the largest alignment requirement.
⬥ Alignment gaps are part of the length of a structure.
Example
The following alignment gaps (A) appear in the following structure:
[ a | A | b | A | cccccccccccc | AA | dddd ]
The first alignment gap is constructed as a result of the alignment of the substructure struc2, the second gap is due to the alignment of the component c of type c, and the third is due to the component d of type i.
DATA:
BEGIN OF struc1,
a TYPE x LENGTH 1,
BEGIN OF struc2,
b TYPE x LENGTH 1,
c TYPE c LENGTH 6,
END OF struc2,
d TYPE i,
END OF struc1.
3. Memory Management of Deep Objects
All data types whose data object content represents the actual work data are referred to in ABAP as "flat". The elementary data types of a fixed length are flat, as are structures with solely flat components. The memory requirements of flat data objects are statically defined by the data type. Flat data objects are always static data objects.
On the other hand, data types where the contents of the data objects are references (which, in turn, reference work data in another memory area) are referred to as "deep". Deep refers to types of data reference variables and object reference variables as well as to types of strings, internal tables, and boxed components. Strings and internal tables are dynamic data objects whose memory requirements can change at program runtime and are managed internally using references. Reference variables are static data objects since their actual size is defined, whereas the size of the explicitly referenced objects is dynamic. Boxed components are between these two extremes since their memory requirements have not already been defined when the program is started in the internal session, but they can be handled like static data objects with a fixed length. Structures are referred to as deep, regardless of their nesting attributes, if they contain at least one deep component.
When using deep data objects, working memory is requested at program runtime. In the case of reference variables, this is the memory for management information and the objects created (instances of classes and anonymous data objects). In the case of dynamic data objects (strings, internal tables) and boxed components, this is the memory for management information and for the data objects themselves. Objects referenced by reference variables can themselves, in turn, be dynamic - that is, they are or contain strings or internal tables.
◈ Memory Requirements for Deep Data Objects
The memory requirement for a deep data object consists of constantly required memory for the reference and dynamically required memory for the header and the actual objects.
◉ The memory requirement for the reference is 8 byte. With data and object references, this is the memory requirement of the explicitly declared reference variable. With strings, internal tables, and boxed components, an implicit reference is created internally. As long as no dynamic memory is requested, the memory requirement for a string, internal table, or boxed component is exactly 8 bytes.
◉ The dynamic memory consists of a header (string header, table header, box header, or object header) and the actual data (string, table body, substructure, anonymous data object, or class instance). The reference points to the header, which in turn contains the address of the actual data and additional management information. The following graphic illustrates the memory usage of deep data objects.
Dynamic memory (header and data) is requested:
◉ For data and object references by creating objects
◉ For dynamic data objects (strings and internal tables) by inserting content. For internal tables, the memory is requested in blocks. The initial size of a block can be influenced by the INITIAL SIZE addition when defining an internal table.
◉ For boxed components by canceling initial value sharing.
When a deep data object is initialized with CLEAR, REFRESH (obsolete), or FREE, the actual data is deleted, but the reference variables and, for dynamic data objects also the header, are retained. The latter is reused when memory is requested again. The memory requirement of a dynamic data object that is used once and then deleted therefore consists of the reference and the memory requirement of the header, with the exception of boxed components. Only when using the FREE statement on internal tables are table headers sometimes deleted if they would take up too much memory. For static components, initializations do not currently cause memory to be released. Initializing a static box in which initial value sharing has been canceled does not delete the instance in the internal session and assigns its type-friendly initial value to the instance instead.
The memory requirement of the different headers is approximately as follows:
◉ For performance reasons, the memory usage of a string header depends on the length of the string. Strings with a length of less than around 30 characters/60 bytes are called short strings. The memory overhead of the string header of short strings is between approximately 10 and 40 bytes, depending on the length of the string. For all other strings, the overhead is approximately 50 bytes, regardless of the string length.
◉ A table header of an internal table that dynamic memory has already been requested for is around 100 bytes, regardless of the line usage. For filled internal tables, about another 50 or 100 bytes is required for pointers, depending on whether the architecture is 32 or 64-bit.
◉ A box header of a boxed component always uses approximately 20 to 30 bytes.
◉ An object header always uses around 30 bytes.
For internal tables, there are additional row-related management costs in the header. This memory is not created in the table header, but is created in parallel to the table body. This means that when rows are deleted, the corresponding management data is also deleted.
The exact memory requirement of a deep data object can be determined in the ABAP Debugger using the memory consumption function and by creating a memory snapshot for the Memory Inspector.
Note
Deleting rows in internal tables using DELETE does not usually free any memory in the internal table. Statements such as CLEAR or FREE must be used to free memory in internal tables.
◈ Maximum Size of Dynamic Data Objects
In addition to the maximum memory size that the current internal session can request for dynamic data objects, their maximum size is limited by the following factors:
◉ An upper limit for the amount of digits in strings and rows in internal tables results from the fact that they are adressed internally and in ABAP statements using 4 byte integers, which limits them to 2147483647.
◉ The size of strings and hashed tables is limited by the biggest memory block that can be requested in one chunk. This is a maximum of 2 GB and is usually further limited using the profile parameter ztta/max_memreq_MB. For strings, the value of the profile parameter directly represents the maximum size that can be occupied. The maximum amount of rows in hashed tables depends on the required size of the hash administration that has to be stored there. Currently, it can be calculated from the largest power of two that fits into the value of the profile parameter divided by 8. For example, if the profile parameter specifies 250 MB, a hashed table can contain a maximum of roughly 16 million entries (128 times 1024 to the power of two divided by 8).
The actual maximum size is generally less than given by the above limits, since the overall available memory is normally not only used by a string or an internal table.
Note
If there is only little memory space available, it may be better to use an internal table, because its memory space is requested in blocks, while the entire memory space required for a string must always be free as a whole.
◈ Sharing Between Dynamic Data Objects
When reference variables are assigned, only the references are copied. After an assignment, source and target variables point to exactly the same data object or the same instance of a class (to the header).
Sharing takes place internally when assignments are made between strings and similar internal tables that have row types that do not contain table types. This means that the actual data values are not copied for the time being. Only the necessary administration entries are copied, so that the target object refers to the same data as the source object.
In the case of strings, a new internal reference is created that points to the existing string header. In the case of internal tables, a new internal reference is created along with a new table header that refers to the existing table body.
Naturally, sharing between dynamic data objects is active only as long as multiple dynamic data objects are involved or if more than one internal reference points to the data values. As soon as only one internal reference points to the data, sharing becomes inactive. This can occur, for example, if dynamic data objects only exist during the lifetime of a procedure or are recorded as anonymous data objects by Garbage Collector.
Active sharing between existing dynamic data objects is canceled at the precise moment when either the source object or target object is accessed in change mode (copy-on-write semantics). The data values are then copied and the references and headers modified accordingly.
The following figure illustrates how dynamic data objects are shared. The upper left section shows how strings are shared and the right section shows how internal tables are shared. The lower section shows how sharing is terminated when the source or target object is modified.
Notes
1. Table sharing is principally used only for tables whose row types do not themselves contain table types. Otherwise, the prerequisite for "similar tables" is kept deliberately vague. Tables are considered to be similar if they at least have the same table type, that is, the same row type, table category, and keys. Additional table combinations are also considered to be similar and may be shared. However, this is an internal optimization measure that may change between releases. This means programming must never be based on when table sharing occurs and when it is canceled again.
2. Sharing also occurs in pass by value to procedures.
3. Sharing is also supported when accessing shared objects as long as an area instance version is bound to the current internal session using an area handle.
4. Sharing is not canceled when objects are modified for reference variables that refer to the same data object or the same instance of a class.
5. Another kind of sharing is the initial value sharing of boxed components for which the initial value is stored only once for each application server.
◈ Complex Data Objects with Deep Components
If data objects of complex data types have many deep components, which often, for example, applies to internal tables with a deep row type, the management costs (in the form of memory) for references and header must be prevented from growing disproportionately large compared to the actual data content.
For complex data objects with relatively little data content, three basic cases can be distinguished:
1. Complex data objects with a sparse fill level
A complex deep data object is sparsely populated if it contains many deep components of which a majority is initial. The required memory of a deep initial component like this is 8 bytes, unless the component does not yet refer to a header.
2. Complex data objects with a duplicative fill level
A complex deep data object has a duplicative fill level if it contains many deep components of which a majority refers to the same data. Components like this share the dynamic memory and only contribute to their references with the required memory. For dynamic data objects, this is achieved by sharing.
3. Complex data objects with a low fill level
A complex deep data object has a low fill level if it contains many deep components that refer to different objects, strings or internal tables in which the objects only require very little memory or are empty.
Deep data objects with a fill level that is sparse, duplicative, and not too low are generally harmless.
For deep data objects with a sparse fill level and few duplicative parts , it is vital to consider the memory requirements for references and headers. Unlike other programming languages, ABAP is inappropriate for massive use of data objects like this. A class wrapper is one possible alternative to internal tables at a low dataset level, since the extra costs for objects are comparatively low.
Example
An example of a duplicative data object with a low fill level is an internal table whose row type is itself table-like or contains table-like components. Even if the interior internal tables are initialized after prior usage, they still occupy memory for reference and header, which, in the case of a large exterior internal table, can produce considerable memory requirements for little or no work data.
◈ Deep Data Objects, Memory Consumption
The example illustrates the management costs of deep components with low data content.
Source Code
REPORT demo_memory_usage.
CLASS lcl DEFINITION.
PUBLIC SECTION.
DATA atab TYPE TABLE OF i.
ENDCLASS.
CLASS demo DEFINITION.
PUBLIC SECTION.
CLASS-METHODS main.
ENDCLASS.
CLASS demo IMPLEMENTATION.
METHOD main.
CONSTANTS n TYPE i VALUE 1000.
DATA: itab TYPE TABLE OF i,
dref TYPE REF TO i,
rtab TYPE TABLE OF REF TO i,
ltab TYPE TABLE OF i,
ttab LIKE TABLE OF ltab,
oref TYPE REF TO lcl,
otab TYPE TABLE OF REF TO lcl.
FIELD-SYMBOLS <line> TYPE any.
DO n TIMES.
APPEND sy-index TO itab.
CLEAR dref.
CREATE DATA dref.
dref->* = sy-index.
APPEND dref TO rtab.
CLEAR ltab.
APPEND sy-index TO ltab.
APPEND ltab TO ttab.
CLEAR oref.
CREATE OBJECT oref.
APPEND sy-index TO oref->atab.
APPEND oref TO otab.
ENDDO.
BREAK-POINT ##no_break.
LOOP AT itab ASSIGNING <line>.
FREE <line>.
ENDLOOP.
LOOP AT rtab ASSIGNING <line>.
FREE <line>.
ENDLOOP.
LOOP AT ttab ASSIGNING <line>.
FREE <line>.
ENDLOOP.
LOOP AT otab ASSIGNING <line>.
FREE <line>.
ENDLOOP.
BREAK-POINT ##no_break.
ENDMETHOD.
ENDCLASS.
START-OF-SELECTION.
demo=>main( ).
Description
At the breakpoints, you can use the ABAP Debugger to display the memory requirements of the four internal tables itab, rtab, ttab, and otab.
At the first breakpoint, the four tables have the same dynamic yet not duplicative data content, that is, 1000 different integers. Whereas for itab, the data content size of about 4 MB is only increased by the management costs for itab itself amounting to around 100 bytes, all other tables create management costs for each single table row. For the deep row types in rtab, ttab, and otab, the data content size of 4 MB is confronted with management costs in the order of 100, 200 and 300 MB. The costs for the inner internal table in ttab are higher than that for the data reference in rtab. The management costs for otab are made up of the costs for the object references and for the internal tables in the object references.
At the second breakpoint, all rows of each of the four tables were initialized using FREE. Of course, this does not effect the memory requirements of itab. In rtab, all data as well as all management information of the individual reference variables was deleted, leaving memory requirements of about 8 MB for the initial references plus the management costs for rtab itself. In ttab, all data was deleted but the individual table headers were retained. Although the management costs could be reduced slightly this way, this still leaves about 100 MB of pure management costs. For otab, by contrast, the situation was similar to rtab, leaving only the costs for the initial references.
This example shows on the one hand that for internal tables with deep row types the management costs may easily exceed the data content and on the other hand that after deleting data a table with object references is less expensive than a table with inner tables.
◆ Validity and Visibility
The context of a declarative statement in the source code of a program determines the validity and visibility of the declared component. In ABAP programs, there are three contexts in which data types and data objects can be declared:
◇ Locally in procedures
Local data in procedures is valid while a procedure is being executed. It is created when the procedure is called, and deleted when the procedure is exited. In addition to their local data and formal parameters, procedures also 'see' the global data of the master program. Methods also 'see' the components of their class.
◇ As components of classes
Static attributes of classes exist for as long as the internal session of the ABAP program. Instance attributes of classes are related to the lifetime of objects. They are created when an object is instantiated and deleted along with the object by the garbage collector. Classes also see the global data of the master program.
◇ Globally in the master program
Global program data exists as long as the internal session of the ABAP program. The data is created when the program is loaded in the internal session, and deleted from the internal session when the program is removed. An ABAP program normally only sees its own global data (with the exception of interface work areas).
All contexts see the cross-program type definitions in ABAP Dictionary and the type definitions and data declarations in the public visibility sections of global classes. Local declarations, however, hide global declarations with the same name. In statements, in which a dynamic specification of a data type, a class or an interface is possible, the hiding of a global type by a local type can be cancelled by specifying an absolute type name.
In addition to context-dependent visibility, the position of the declaration in the source code also plays a role. In a statement of an ABAP program only previous declarations are visible, regardless of the context. To enable the order in the program to match the context-dependent visibility, all global declarations of a program should be specified at the start of the source code, before the first processing block, and all local declarations should be specified directly after the introduction of a procedure. Viewed like this, the definition of an interface and the declaration part of a class are both global declarations. Remember that reference variables that reference a class cannot be declared until after the class has been declared. The implementation part, on the other hand, is one of the processing blocks.
Note
All data declared in the declaration part of an ABAP program is global to the program. With the exception of the event blocks AT SELECTION-SCREEN, all data declared within event blocks and dialog modules is global to the program. The data declared in the above event blocks is local to these event blocks. Data that is declared between discrete processing blocks is also global for the program.
◆ Absolute Type Names
The type name that can be used statically in ABAP statements is relative to its context, and is also known as the relative type name. As described in Validity and Visibility, local data types hide more global data types of the same name. The same applies to classes and interfaces, which can also be interpreted as type definitions in this regard.
Absolute type names, however, name a type uniquely. An absolute type name as a specified path is composed of the following components:
⬙ \TYPE=name
⬙ \CLASS=name
⬙ \INTERFACE=name
⬙ \PROGRAM=name
⬙ \CLASS-POOL=name
⬙ \FUNCTION-POOL=name
⬙ \TYPE-POOL=name
⬙ \METHOD=name
⬙ \FORM=name
⬙ \FUNCTION=name
The last component of a path must always be \TYPE=name, \CLASS=name, or \INTERFACE=name. It describes a data type, a class, or an interface. The name must be entered in uppercase letters. Absolute type names that only consist of \TYPE=name, \CLASS=name, or \INTERFACE=name describe a data type from ABAP Dictionary or a global class/interface of the class library. To create absolute type names for local data types, classes, and interfaces, use sequential component names that specify its context as prefixes.
Absolute type names can be used in all statements in which a data type, a class, or an interface can be specified dynamically. This makes it possible to stop a local type from obscuring a global type by specifying an absolute type name, and the absolute type names can be used to access the types, classes, and interfaces of other programs dynamically. It is possible to load a different program into the current internal session if this is necessary to access the program.
A data type is uniquely identified by its absolute type name. Various options exist, however, for forming an unique path for a type. For example, the function group can be omitted for a type in a function module, because every function module is unique. If types are located in a class pool or function group, the technical name name of the ABAP program can also be specified. Since the latter is not known most of the time, it is best to use \CLASS-POOL or \FUNCTION-POOL instead.
A data type that only exists as a property of a data object does not have a relative type name. However, internally it has an absolute type name (technical type name) that uniquely defines the data type.
Notes
1. The type description classes of the Run Time Type Services (RTTS), such as CL_ABAP_TYPEDESCR, contain methods that return the absolute type name of data types or data objects.
2. If an absolute type name is used in a program to specify a type of a different program, this program is added to a new additional program group or to the current program group, if not already loaded. The program constructor LOAD-OF-PROGRAM is not yet executed.
Example
When the methods m1 and m2 of the class c1 are called in the following example, the RTTS get the absolute type names \TYPE=SPFLI or \PROGRAM=RTTI_TEST\CLASS=C1\METHOD=M2\TYPE=SPFLI for the generically typed parameter p. The use of the name spfli has different meanings in the methods m1 and m2. A syntax check warning provides a reminder of this.
CLASS c1 DEFINITION.
PUBLIC SECTION.
METHODS: m1,
m2,
m3 IMPORTING p TYPE any.
ENDCLASS.
CLASS c1 IMPLEMENTATION.
METHOD m1.
DATA struc TYPE spfli.
m3( struc ).
ENDMETHOD.
METHOD m2.
TYPES spfli TYPE spfli.
DATA struc TYPE spfli.
m3( struc ).
ENDMETHOD.
METHOD m3.
DATA type_descr TYPE REF TO cl_abap_typedescr.
type_descr = cl_abap_typedescr=>describe_by_data( p ).
WRITE / type_descr->absolute_name.
ENDMETHOD.
ENDCLASS.
◆ Compatible Data Types
The compatibility of two data types (except reference types) is based on the technical type attributes of the data types. It forms the basis for type checking during assignments to field symbols or when assigning actual parameters to formal parameters.
In addition, the compatibility determines whether with value assignments and comparisons between data objects except reference variables a conversion has to be performed or not.
In the case of reference types with data objects (reference variables) that have a dynamic type as well as the static type, then compatibility, which is based entirely on technical type attributes, is not sufficient.
1. Non-Generic Data Types (Except Reference Types)
2. Generic Data Types
3. Reference Types
1. Non-Generic Data Types (Except Reference Types)
Two non-generic data types except reference types and types that contain reference types as components are compatible if all their technical type attributes match.
◔ For elementary data types, the technical type attributes are:
◔ the predefined ABAP type
◔ the length (for types c, n, p, x)
◔ the number of decimal places (for type p)
With compatible elementary data types, all these attributes match.
◔ For structured types, the technical type attribute is:
◔ the component structure
The structure of structured types does not only refer to the sequence of elementary components in memory, but also to the combination of components to substructures and whether a substructure is a boxed component. The names of the components and of the semantic attributes defined in ABAP Dictionary, such as conversion routines or documentation, however, are not important. With compatible structures, all components are compatible in pairs. This applies recursively down to the level of elementary data types.
If two structures are both constructed identically but different substructures are declared as boxed components, then the structures are not compatible.
◔ For table types, the technical type attributes are:
◔ the row type
◔ the table category
◔ the table key
With compatible internal tables, the row types are compatible and table category and table key match. Other attributes, such as the initial memory requirement, are not important.
◔ For mesh types, the technical type attributes are:
◔ node structure including node names
◔ associations (defined by ON conditions) of every component, including names and used table key
Note
The types listed here are not compatible with one another - for example, an elementary data type is never compatible with a structure, even if the structure has only one component.
2. Generic Data Types
A non-generic data type except a reference type is compatible with a generic data type if its technical attributes are included into the generic data type.
3. Reference Types
A reference type is the static type of reference variables and determines to which objects they can point. At runtime, reference variables also have a dynamic type determined by the type of the object, which a reference variable points to. The dynamic type may be more specialized than the static type. For this reason, the rules for typing checks, assignments and comparisons cannot be covered by the idea of a compatibility that is based entirely on the technical attributes of the static type. Instead, the following three issues show how reference types can be used together:
◔ When checking typings, a reference variable can
◔ be passed to a formal parameter typed as a reference variable, provided that the type of the formal parameter is more general or equal to the type of the formal parameter (Up Cast) and the formal parameter cannot be changed within the procedure.
◔ be assigned to a field symbol typed as a reference variable, provided that the reference types are identical.
◔ Assignments between reference variables can be carried out by using an up cast or a down cast.
◔ Data reference variables can be compared to all data reference variables and object reference variables can be compared to all object reference variables.
As a rule, data reference variables can only be used with data reference variables and object reference variables only with object reference variables. Reference variables are never converted. They are either passed without conversion or assigned to each other or compared to each other or not.
Notes
◔ These rules for the usability of reference variables for assignments is one-way. The type of a target reference variable, to which a source reference variable can be assigned, does not itself have to be assignable to the source reference variable. In contrast, the usability of reference variables in the case of comparisons is not a one-way relationship.
◔ If a reference variable is a component of a structure, the usability of the structure is determined accordingly. In particular, the usability of this structure type with regard to assignments is also a one-way relationship.
◆ Details of Special Data Types or Data Objects
- Numeric Data Types
ABAP supports the numeric data types: i, int8, p, decfloat16, decfloat34, and f, plus the internal types b and s. The latter cannot be specified directly in programs but are created when the predefined types INT1 or INT2 from ABAP Dictionary are referenced. They are generally used in the same way as the type i and are often converted to i internally.
The numeric data types are intended for calculations. Calculations involving fields of the types i, int8, and type f correspond more or less directly to the operating system's machine commands for the current application server. In contrast, calculations involving packed numbers of type p are programmed in the kernel of the ABAP runtime environment and are therefore somewhat slower. Operations using the decimal floating point numbers decfloat16 and decfloat34 run using a library integrated into the ABAP kernel, until they are supported by the hardware of the application server.
1. Integer Numbers
The data types for integer numbers i and int8 have a value range from -2147483648 to +2147483647 for i and -9.223.372.036.854.775.808 to +9.223.372.036.854.775.807 for int8 and only cover integers. Integer numbers with the type i can be specified directly in the program as numeric literals.
Intermediate results in arithmetic expressions of the calculation type i or int8 are stored in auxiliary fields of the type i or int8. Otherwise, type i or int8 arithmetic is similar to performing calculations with type p without decimal places. In particular, division rounds numbers rather than truncating them and an overflow raises an exception. The data types i and int8 are typically used for counters, quantities, indexes, and offsets, as well as time periods.
Note
The data types b, s, i, and int8 provide a complete set of data types for single-byte, 2-byte, 4-byte, and 8-byte integers numbers. The types b and s for short integer numbers, however, cannot be specified directly in ABAP programs. Instead they have to be specified by using the predefined types INT1 and INT2 from ABAP Dictionary. These types do not have their own calculation type.
2. Packed Numbers
The data type p for packed numbers has a value range that depends on their length and the number of decimal places. Data objects of type p can be 1 to 16 bytes long, with two places packed into each byte, and one place and the sign packed into the last byte. A packed number consists of the length x 2 minus 1 digits and can have a maximum of 14 decimal places. Packed numbers are used to implement fixed point numbers. The decimal places in a packed number are an attribute of its data type and are fixed for this type.
Packed numbers with decimal places cannot be specified directly in the program. Instead, character literals must be used whose content can be interpreted as a packed number, that is, it represents a number in mathematical or commercial notation. Scientific notation is not permitted unless it can be interpreted as a mathematical notation.
Auxiliary fields for intermediate results in arithmetic expressions of calculation type p are always 16 bytes long and can thus hold up to 31 places. Before an overflow, an arithmetic expression is calculated again with auxiliary fields that are twice as large or 63 places. In the case of comparisons between packed numbers, the operand with fewer decimal places is also converted into an auxiliary field of this type, though an overflow occurs if the sum of the integer digits and decimal places exceeds 31.
If packed numbers are used, the program attribute must always be set to fixed point arithmetic since only this setting ensures that the decimal point is correctly calculated. Otherwise, all numbers are specified as integers and all intermediate results are rounded up to the next integer. If fixed point arithmetic is not configured, the decimal places defined for the number only appear in dynpro output or when formatting with WRITE [TO].
Calculations using calculation type p are performed using fixed point arithmetic. In other words, a calculation is performed "commercially", similarly to using a pocket calculator or paper and pencil. Type p is typically used for values such as lengths, weights, and sums of money.
Note
The number of decimal places in a packed number should be no greater than the number of digits; otherwise the decimal separator might be outside the sequence of digits.
3. Decimal Floating Point Numbers
The data types fordecimal floating point numbers are decfloat16 and decfloat34. The value range is 1E385(1E-16 - 1) through -1E-383, 0, +1E-383 through 1E385(1 - 1E-16) for decfloat16 and 1E6145(1E-34 - 1) through -1E-6143, 0, +1E-6143 through 1E6145(1 - 1E-34) for decfloat34. The maximum precision is 16 places or 34 places, respectively. As well as its value, a decimal floating point number has a scale and a precision. These properties are not relevant for calculations and comparisons of values, but are used in conversion rules and for formatting output.
Decimal floating point numbers with decimal places or exponents cannot be specified directly in the program. Instead, character literals must be used whose content can be interpreted as a packed number, that is, it represents a number in mathematical, scientific, or commercial notation.
Arithmetic expressions with decimal floating point numbers always have the calculation type decfloat34. Each calculation is made with decimal floating point arithmetic. Decimal floating point numbers are the best choice if precision and a large range of values are of importance. They do not have the disadvantages of binary floating point numbers described below. These binary floating point numbers cannot represent each decimal number in their value range exactly. Decimal floating point numbers have a much large value range and a higher level of precision than packed numbers.
By using the lossless operator EXACT, it is possible to force a lossless calculation for decimal floating point numbers under certain circumstances. No rounding is permitted in lossless calculations and raises an exception.
Internally, decimal floating point numbers are represented by a 16-digit or 34-digit decimal mantissa and a decimal exponent. The exponent is between -383 and +384 or -6143 and + 6144, respectively. Apart from potential roundings in assignments and calculations, the effects discussed below for binary floating point numbers are not observed. This is because every 16-digit or 34-digit decimal number can be represented exactly.
4. Binary Floating Point Numbers
The data type for binary floating point numbers, f, has a value range of 2.2250738585072014E-308 through 1.7976931348623157E+308, positive as well as negative, and the number 0, with an accuracy of at least 15 places. 17 places are represented in ABAP. Integers can be represented exactly up to an absolute value of 2**53, which is equivalent to 9,007,199,254,740,992. Any larger numbers are rounded.
Binary floating point numbers cannot be specified directly in the program. Instead, character literals must be used whose content can be interpreted as floating point numbers, that is, it represents a number in scientific notation. Mathematical or commercial notation is not permitted unless it can be interpreted as scientific notation.
Arithmetic expressions with calculation type f are performed using binary floating point arithmetic. Be aware of the following features of binary floating point arithmetic.
Internally, binary floating point numbers are stored separately, each in two parts. This can produce unexpected results despite the high degree of intrinsic accuracy. These occur mainly when performing conversions from and to type f.
◇ For example, the number 1.5 can be represented exactly in this notation since 1.5 = 1*2**0 + 1*2**(-1), but the number 0.15 can only be represented approximately by the number 0.14999999999999999. If 0.15 is rounded up to 1 valid digit, the result is 0.1 rather than 0.2 as might be expected. On the other hand, the number 1.5E-12 is represented by the number 1.5000000000000001E-12, which would be rounded up to 2E-12.
◇ A further real-life example: 7.27% of 73050 is to be calculated and rounded to 2 decimal places. The intermediate result is 5.3107349999999997E+03, since the correct result, 5310.735, cannot be represented exactly in two parts with 53 bits. (If the hardware cannot represent a real number exactly, it uses the next representable binary floating point number). After rounding, the result is 5310.73, rather than 5310.74 as might be expected.
The ABAP runtime environment always calculates commercially and not numerically like the underlying machine arithmetic. According to the rounding algorithm of the latter, the end digit 5 must always be rounded to the nearest even number (not the next largest number), that is, from 2.5 to 2 and from 3.5 to 4.
Note also that multiplication using powers of 10 (positive or negative) is not an exact operation.
◇ Example: Although it can be represented exactly in two parts, a binary floating point number f of value 100.5, after the operation
f = f / 100 * 100.
has the value 100.49999999999999.
As well as rounding errors, the restricted number of places for the mantissa can cause trailing digits to be lost.
◇ Example: 1 - 1.0000000000000001 produces zero.
This means that the last places in binary floating point arithmetic are not reliable. In particular, it is not usually worth testing two binary floating point numbers a and b for equality; instead, it is best to check whether the relative difference abs((a - b)/a) is less than a predefined limit, such as 10**(-7).
Ultimately, the display and therefore the value of a binary floating point number stored in a database can be platform-dependent.
Note
To assign numeric values to text fields and text strings, instead of using a conversion it is often better to use the statement WRITE ... TO or embedded expressions in string templates with the associated formatting options.
The common generic type of the numeric data types is numeric.
- Strings
Strings are elementary data objects of variable length. Strings can be either text strings or byte strings. Like internal tables, strings belong to the dynamic data objects.
The corresponding predefined ABAP types are string and xstring. These are the dynamic equivalent of the data types c and x, which define text or byte fields of fixed length. Text strings and text fields contain character strings. Their common generic type is csequence. Byte strings and byte fields contain byte strings. Their common generic type is xsequence.
Unlike a text field or byte field, the length of a string is not statically determined, but rather is variable and adapts to the current content of the data object at runtime. Internally, this uses dynamic memory management (see Memory Management for Deep Data Objects). The maximum size of a string is determined by the profile parameter ztta/max_memreq_MB (see Maximum Size of Dynamic Data Objects). The initial value of a string is the empty string with length 0.
In contrast to text fields, trailing blanks are respected in text strings. There is a special text string literal for text strings. As with byte fields, there is no special literal for byte strings in the current release.
Strings belong to the deep data types. A structure that contains a string is a deep structure and cannot be used as a character-like field in the same way as a flat structure.
Strings, like internal tables, can be stored in data clusters. In ABAP Dictionary, strings can have the predefined data types SSTRING, STRING, and RAWSTRING. These can also be the types of table fields in database tables (subject to certain restrictions).
- Reference Types
References are pointers to instances. Pointers to data objects are known as data references. Pointers to instances of classes are known as object references. In ABAP, references occur as the content of reference variables. Reference variables are data objects whose data type is a reference type.
Reference types are always created with the addition REF TO. The content of reference variables can be checked using the predicate expression IS BOUND.
The reference type is the static type of a reference variable. It defines the types of the instances its references can point to. The dynamic type of a reference variable is the type from which an object (to which a reference variable points) was instanced. The static type is always more general than or the same as the dynamic type. A dynamic type can be a data type or a class. A reference type or static type can be a type for a data reference variable or object reference variable. The latter is subdivided into class reference variables and interface reference variables.
Special conversion rules apply for assignments between reference variables, depending on the static type. These rules ensure that the dynamic type is never more general than the static type (up cast, down cast).
Depending on where the object referenced by a reference variable is located, memory-retaining heap references or non-memory-retaining stack references are used.
1. Data References.
Data references can point to any data objects or to their parts (components, rows of internal tables, or sections determined by offset and length specifications). The static type of their reference variables is either the predefined generic type data or any non-generic data type. Data reference variables can be used in the statement CREATE DATA to generate data objects dynamically. The statement GET REFERENCE and the reference operator REF can be used to write references to existing data objects in data reference variables. When internal tables are processed, most statements have the addition REFERENCE INTO, to set references to table rows.
The dereferencing operator ->* is used to access the data object to which a data reference points. If the static type of the data reference variable is not generic, the expression dref->* can be specified at any operand position. For data reference variables with a generic static type, only the statement ASSIGN dref ->* TO <fs> can be used to assign the data object (to which the data reference points) to a field symbol.
2. Object References
Object references can point to instances of classes. The static type of their reference variables is either a class or an interface. You can use both types to generate objects with the statement CREATE OBJECT.
Class reference variables allow access to all visible components of a class.
Interface reference variables restrict the view of the interface components of a class.
Object references are always heap references.
3. Heap references and stack references
The objects referenced by references can be located in the heap or in the stack. Objects in the heap are instances of classes or are anonymous data objects. Objects in the stack are the global data objects of programs and the local data objects of procedures stacked there.
◈ Heap references point to objects or parts of objects in the heap
Heap references are object references or data references. They are created either when new objects are created in the heap (using the statements CREATE OBJECT or CREATE DATA) or by applying the statement GET REFERENCE or the addition REFERENCE INTO to data objects in the heap. Heap references are always memory-preserving, which means that, as long as a heap reference points to an object or a part of an object, then the object is not deleted by Garbage Collector.
◈ Heap references point to objects or parts of objects in the heap
Stack references are always data references and are created only by applying the statement GET REFERENCE, the reference operator REF, or the addition REFERENCE INTO to data objects in the stack stack. Stack references are not memory-preserving.
A non-initial object reference always points to an instance of a class, which means it is always a heap reference. A data reference can be a heap reference or a stack reference:
◈ A data reference is a heap reference if it
◈ points to an instance attribute or a part of an instance attribute of an object,
◈ points to an anonymous data object or a part of an anonymous data object.
◈ A data reference that points to a data object or a part of a data object in the stack is a stack reference.
A part of a data object is either a component of a structure, a row of an internal table, or a section specified by an offset/length.
Heap references preserve the memory and cannot become invalid, with one exception: A heap reference to a row in an internal table becomes invalid if the table row is deleted. Stack references also become invalid if the referenced data object is removed from the stack (that is, if the associated procedure is ended). The latter also applies to the local data in instance methods. The predicate expression IS BOUND for an invalid reference is false.
Notes
◈ Field symbols have the same properties with respect to preserving memory and validity as data references. Field symbols to which objects or parts of objects are assigned in the heap are memory-preserving.
◈ Internal tables are dynamic data objects and have a special role because they have their own memory management. They allocate and release memory regardless of the statement CREATE and Garbage Collector. This means that heap references to rows in internal tables can become invalid. This is not the case for strings, since no references to substrings of strings are allowed.
◈ A reference is classified as a heap reference or a stack reference depending on its value only, and not by the type of the reference variable in which it is stored. In particular, assignments between reference variables do not change the relevant properties of the copied references.
- Structures
Structures are data objects (comprised of components of any data type) that are saved in sequence in the memory. The data type of a structure is a structured type or a structure defined in ABAP Dictionary, including database tables and views.
In a program, a structured type or structure is created using the additions BEGIN OF ... END OF of the statements TYPES, DATA, and so on. They can also be created dynamically using RTTC methods.
1. Types of Structures
Structures are named as follows (depending on the type of the component):
◆ Flat structures do not contain any deep components. They only contain components with flat data types, such as elementary types c, n, d, t, decfloat16, decfloat34, f, i, int8, p, x, plus b, s (or structures with these types).
◆ Flat character-like structures are flat structures that contain only character-like components.
◆ Nested structures contain at least one substructure. A nested structure is flat or character-like, depending on the attributes of all of the components.
◆ Deep structures contain at least one deep component, at any nesting level. Possible deep components include strings, internal tables, boxed components, data references, or object references.
A structure that contains static or dynamic components is (formally) a static or dynamic data object, respectively.
The following figure illustrates a deep structure.
Note
The term "nested structure" must not be confused with the term "deep structure". A nested structure is flat if it only contains flat components and subcomponents. A nested structure is deep when it has at least one deep component or subcomponent.
2. Boxed Components
The substructures of nested structures and structured components of classes or interfaces can be declared as boxed components.
3. Using Structures
Structures are addressed either fully or by component, at appropriate operand positions. The structure component selector (-) is used for the latter case. Special conversion rules apply to assignments that involve structures.
Flat character-like structures differ in that they can be used like character-like data objects and included in the generic ABAP type clike. They can be placed in all operand positions where elementary character-like data objects are possible. The ABAP runtime environment then interprets the structure as an elementary field of the type c in the length of the structure.
1.1 Using Deep Structures
The data content of deep structures is not saved in full within the memory bounds of the structure and the deep components are instead just references to the actual data. This means that some general restrictions apply when using deep structures (unlike flat structures):
◈ Deep structures must be compatible in assignments and comparisons.
◈ Substring access using offset/lengths is not possible for deep structures.
◈ Deep structures cannot be used as character-like data objects in operand positions and are not included in the generic ABAP type clike. This applies in particular to structures that contain strings.
◈ When data objects are cast with ASSIGN, the type, position in the type of the data object, and the position in the type of the field symbol must match for deep components in deep structures.
◈ The work area of Open SQL statements cannot contain any deep components other than strings or LOB handles
◈ The target or source field of the statements OPEN DATASET and TRANSFER cannot be a deep structure.
◈ Internal tables with a deep row type cannot be passed to a TABLES parameter in a remote function call. Deep structures can be passed to the other parameters, as long as they do not contain any reference variables.
Note
These restrictions are particularly important if single components in existing flat character-like structures are converted to strings, which makes the entire structure deep.
1.2 Using Deep ABAP Dictionary Structures
The same restrictions apply to deep structures defined in ABAP Dictionary as to deep structures defined in ABAP programs. Further restrictions apply only when the following language elements forbidden in classes are used (only flat ABAP Dictionary structures can be specified in classes):
◈ Statement TABLES for table work areas
◈ Obsolete use of LIKE instead of TYPE as a reference to data types in ABAP Dictionary with type declarations and typings
◈ Obsolete use of INCLUDE STRUCTURE
◈ Obsolete forcing of a structure STRUCTURE to field symbols or interface parameters of function modules or subroutines
- Boxed Components
Boxed components are structures that are not saved in the higher-level context itself. Instead, an internal reference that points to the actual structure is stored in place of the structure. A boxed component is always a deep component of its context.
Notes
◈ Boxed components are a halfway house between static and dynamic data objects. Their memory requirement has not already been defined when the program is started in the internal session, but they can be handled like static data objects with a fixed length.
◈ A nested structure that contains a boxed component as a component is always a deep structure.
◈ Structures in ABAP Dictionary can also contain boxed components. ABAP Dictionary database tables cannot contain any boxed components as their structures have to be flat.
◈ In the classes and objects of the RTTS, boxed components are handled as follows:
◈ The class CL_ABAP_TYPEDESCR contains the constant TYPEKIND_BREF for static boxes. The value of these constants is specified as the type of a static box in the component table COMPONENTS of the class CL_ABAP_STRUCTDESCR or the attribute table ATTRIBUTES of the classes CL_ABAP_CLASSDESCR or CL_ABAP_INTFDESCR.
◈ In the return code of the method GET_COMPONENTS of the class CL_ABAP_STRUCTDESCR or GET_ATTRIBUTE_TYPE of the classes CL_ABAP_CLASSDESCR or CL_ABAP_INTFDESCR, boxed components are specified as type description objects of the class CL_ABAP_REFDESCR, like reference variables. The method GET_REFERENCED_TYPE of this class gets a type description object for the substructure. A type description object of the class CL_ABAP_REFDESCR, which describes a boxed component, cannot be used in the statements CREATE DATA or ASSIGN CASTING.
Static Box
Static boxes are boxed components whose components are known statically and which are subject to initial value sharing. Declarations of static boxes generally require less memory for structures that occur multiple times but are rarely used.
The following can currently be declared as static boxes:
◈ Substructures of structured data with the addition BOXED of the statement TYPES
◈ Structured attributes of classes or interfaces with the addition BOXED of the statement [CLASS-]DATA.
A static box can have one of two states:
◈ Initial value sharing
As long as none of the actions named in the following point were executed, initial value sharing applies to a static box. The internal reference points to a type-friendly initial value for the structure, which is saved exactly once in each application server in the PXA. The memory requirement in the internal session is determined only by the internal reference and its administration.
◈ Revoked initial value sharing
The following actions revoke initial value sharing for a static box:
◔ Writes on the static box or one of its components
◔ Assigning the static box or one of its components to a field symbol using ASSIGN
◔ Addressing the static box or one of its components using a data reference
◔ Using a static box or one of its components as an actual parameter for procedure calls
The internal reference then references an instance of the structure in the current internal session. The memory requirement is the same as for a normal structure plus the administration costs for the internal reference.
In initial value sharing, the memory required for the internal session of a static box is not initially known when the program is executed. However, unlike with real dynamic data objects, the length of a static box is always known statically. In static boxes, the same functions are available as those available for a normal component of the same type. When a structure that contains a static box is accessed, however, it must not be forgotten that it is a deep component.
Notes
◔ Static boxes can be used to optimize the memory requirement of structures that are used more than once. If, for example, the row structure of an internal table contains substructures, the memory requirement of the substructure accumulates without the use of static boxes for each row, even if the substructure is initial. If static boxes are used, initial substructures do not require multiple memories as long as only reads are performed.
◔ In addition to the optimized memory requirements, static boxes generally have a positive impact on runtime performance, because assignments between components for which initial value sharing is active only require the internal reference (and no additional data) to be copied.
◔ The CLEAR and FREE statements do not work as write statements on a static box that has the initial value sharing state, and the state is persisted. On the other hand, once the initial value sharing status is revoked, these statements do not currently free up any memory and provide the local instance of the static box with type-friendly initial values instead.
You can define program-local data types in ABAP programs that can be used for typing or declaring additional data types and data objects according to validity and visibility.
The corresponding statements are:
1. TYPES
Syntax Forms
Using Predefined Types
1. TYPES { {dtype[(len)] TYPE abap_type [DECIMALS dec]}
| {dtype TYPE abap_type [LENGTH len] [DECIMALS dec]}}.
Reference to Existing Types
2. TYPES dtype { {TYPE [LINE OF] type}
| {LIKE [LINE OF] dobj} }.
Reference Types
3. TYPES ref_type { {TYPE REF TO type}
| {LIKE REF TO dobj} }.
Structured Types
4. TYPES BEGIN OF struc_type.
...
TYPES comp ...
TYPES comp TYPE struc_type BOXED.
INCLUDE {TYPE|STRUCTURE} ...
...
TYPES END OF struc_type.
Table Types
5. TYPES table_type { {TYPE tabkind OF [REF TO] type}
| {LIKE tabkind OF dobj} }
[tabkeys][INITIAL SIZE n].
Ranges Table Types
6. TYPES dtype {TYPE RANGE OF type}|{LIKE RANGE OF dobj}
[INITIAL SIZE n].
Client Field for CDS Views
7. TYPES dtype TYPE cds_entitiy CLIENT SPECIFIED clnt.
Mesh Types
8. TYPES BEGIN OF MESH mesh_type.
...
TYPES node TYPE [REF TO] table_type associations
...
TYPES END OF MESH mesh_type.
LOB Handle Structures
9. TYPES dtype TYPE dbtab|view
lob_handle_type FOR lob_handle_columns
[ lob_handle_type FOR lob_handle_columns
... ].
Effect
The statement TYPES defines a standalone data type. Naming conventions apply to the names. The defined data type can be viewed within the current context from this position.
The syntax makes it possible to define elementary data types, reference types, structured types, table types, and mesh types. As well as the types that are completely self-constructed, special types such as ranges table types or LOB handle structures can be derived from existing types.
For the definition of a structured type struc_type, any type definitions of two TYPES statements are included with the additions BEGIN OF and END OF; a structured data type struc_type is defined here, which contains the included data types as components struc_type-.... Structure definitions can be nested. A mesh type is a special structure type whose components are tabular nodes for which associations can be defined.
1.1 TYPES - TYPE abap_type
Syntax
TYPES { {dtype[(len)] TYPE abap_type [DECIMALS dec]}
| {dtype TYPE abap_type [LENGTH len] [DECIMALS dec]}}.
Addition:
... DECIMALS dec
Effect
If a predefined data type abap_type is specified, a non-generic elementary data type is defined. For abap_type, all predefined data types can be used except the internal types b and s.
In the ABAP types c, n, p, and x, the length of the data type dtype must be specified by entering directly a number or a numeric constant len within the length range defined for the type in question. For all other ABAP types, the length is determined by the value in the tables of predefined ABAP types and no length can be specified in len.
The length len is either specified in parentheses directly after the type name dtype, or after the addition LENGTH. The specified length must be positive.
Notes
1. For reasons of legibility, it is best to always use the addition LENGTH, and not parentheses, to specify the length len.
2. It is not necessary to list all additions in obsolete variants of the above statement. These additions are added implicitly.
Example
These statements create three elementary data types that are local to the program. Values for the unspecified technical attributes of the predefined types c and p are specified.
TYPES: text10 TYPE c LENGTH 10,
text20 TYPE c LENGTH 20,
number TYPE p LENGTH 8 DECIMALS 2.
Addition
... DECIMALS dec
Effect
In the ABAP type p, the number of decimal places must be specified using the addition DECIMALS and by specifying an unsigned number directly or a corresponding numeric constant dec. The addition cannot be specified in other data types.
A maximum of 14 decimal places can be specified. If the number of decimal places is greater than the number of places or digits calculated from 2 * len - 1, a warning is produced by the syntax check. This is because only the last 2 * len - 1 decimal places can be filled with digits.
For the decimal separator to be respected in operations involving packed numbers, the program attribute fixed point arithmetic must be set. Otherwise, the addition DECIMALS only affects the output on dynpros and the format for the statement WRITE [TO].
Note
If the number of decimal places is greater than the number of digits, the decimal separator is outside the sequence of digits, which has consequences in assignments and in output.
Example
Defines a numeric type for a packed number with three digits and two decimal places. The value range is -9.99 +9.99 in increments of 0.01.
TYPES number TYPE p LENGTH 2 DECIMALS 2.
Example
Defines a numeric type for a packed number with three digits and five decimal places. This statement produces a syntax check warning. The value range is -0.00999 to +0.00999 in increments of 0.00001. Not all decimal places can be used.
TYPES number TYPE p LENGTH 2 DECIMALS 5.
1.2 TYPES - TYPE, LIKE
Syntax
TYPES dtype { {TYPE [LINE OF] type}
| {LIKE [LINE OF] dobj} }.
Addition:
... LINE OF ...
Effect
If a data type type or a data object dobj is specified, dtype assumes all the properties of the specified data type or data object.
- The following can be specified for type:
- A non-generic data type from ABAP Dictionary allowed by the package check (more specifically, the structure of a database table, of a classic view, or of a CDS entity (CDS view or CDS table function)
- A public type of a global class allowed by the package check
- A non-generic data type of the same program defined previously using TYPES
- A data object that is visible at this point can be specified for dobj. If a field symbol or formal parameter is specified for dobj, the symbol or parameter must be fully typed. The declared type is inherited. The evaluation of the statement does not require a data object to be bound.
If a reference is made to a data type in ABAP Dictionary, its primary components are transformed to predefined ABAP types in accordance with the tables of predefined types in ABAP Dictionary.
Notes
◈ LIKE can be used to refer to data objects, and also to the public attributes of global classes.
◈ A data type that is declared by a direct TYPE or LIKE reference to a boxed component is assigned its data type but is not a boxed component.
Addition
... LINE OF ...
Effect
The optional addition LINE OF can be used if type is a table type or if dobj is an internal table. If this addition is used, dtype inherits the properties of the row type of the internal table.
Example
These TYPES statements define two data types local to the program. The first assumes a table type from a type group of ABAP Dictionary, and the second corresponds to the row type of this table type.
DATA: event_table TYPE cntl_simple_events,
event LIKE LINE OF event_table.
1.3 TYPES - REF TO
Syntax
TYPES ref_type { {TYPE REF TO type}
| {LIKE REF TO dobj} }.
Effect
The addition REF TO specifies a data type for a reference variable. The static type of the reference variable is specified after REF TO. The static type restricts the object quantity to which a reference variable can point. The dynamic type of a reference variable is the data type and the object class to which it points. The static type is always more general or the same as the dynamic type (see also assignment rules for reference variables).
Apart from data and object, no generic data types can be specified after TYPE REF TO.
Types for Data Reference Variables
If the predefined generic data type data is specified for type, a data type for a data reference variable of the generic static type data is created. Reference variables like this can point to any data objects.
If type is specified as any non-generic data type (meaning a non-generic data type from ABAP Dictionary or from the public visibility section of a global class), as a non-generic local program type already defined using TYPES, or as a non-generic predefined ABAP type, a data type is created for a data reference variable with an appropriate static type. Reference variables like this can point to all data objects of the same type.
The same applies to dobj as to TYPES ... LIKE. A data type is created for a data reference variable and the static type of this variable is inherited from the data type of the specified data object. Reference variables like this can point to all data objects of the same type.
A data reference variable can be dereferenced in different ways, depending on its static type:
◈ A data reference variable typed generically with TYPE REF TO data can be dereferenced only in the statement ASSIGN with the dereferencing operator ->*.
◈ A data reference variable typed in full with TYPE REF TO complete_type or LIKE REF TO dobj can be dereferenced in all matching operand positions using the dereferencing operator ->*. If the static data type is structured, the object component selector enables access to the components of the structure with dref->comp.
Types for Object Reference Variables
If the predefined generic data type object is specified for type, a data type for a class reference variable of the generic static type data is created. Reference variables like this can point to instances of any class.
If a global class or local class is specified for type, a data type for a class reference variable whose static type is the specified class is created. Reference variables like this can point to all instances of the class and its subclasses. A class reference variable can be used to access all components of an object. If the static type is the superclass of the dynamic type, the components that can be called statically are a subset of the components of the dynamic type. All attributes and methods of a dynamic type can be called using a class reference variable and the dynamic object attribute call (see ASSIGN) and the dynamic method call.
If a global or local interface is specified for type, a data type for an interface reference variable whose static type is the specified interface is created. Reference variables like this can point to objects of all classes that implement the interface. When calling components of objects with interface references, the name of the static type is always placed implicitly before the component. An interface reference variable can be used to access only those interface components of an object that are known in the static type. This applies to both dynamic and static access.
Notes
◈ The TYPE addition can be used to define data types for data reference variables and object reference variables. Only data types for data reference variables can be defined using the LIKE addition.
◈ The predefined generic data type any can only be specified after TYPE (as is the case with all other generic types apart from data) and cannot be specified after REF TO.
Example
This example shows how data types are defined for an interface reference variable and for a class reference variable and how a data reference is defined with the static type of the interface reference variable.
INTERFACE i1.
...
ENDINTERFACE.
CLASS c1 DEFINITION.
PUBLIC SECTION.
INTERFACES i1.
ENDCLASS.
TYPES: iref TYPE REF TO i1,
cref TYPE REF TO c1,
dref TYPE REF TO iref.
1.4 TYPES - BEGIN OF struct_type
Syntax
TYPES BEGIN OF struc_type.
...
TYPES comp ...
TYPES comp TYPE struc_type BOXED.
INCLUDE TYPE|STRUCTURE ...
...
TYPES END OF struc_type.
Effect
Defines a structured type struc_type. This is introduced using a TYPES statement with the addition BEGIN OF and must finish with a TYPES statement with the addition END OF.
The following can be included between these TYPES statements:
◈ Any TYPES statements, in particular further closed structure definitions.
◈ The definition of static boxes using BOXED.
◈ The statements INCLUDE TYPE and INCLUDE STRUCTURE for including components from other structures.
No structured types can be created that do not have at least one component.
The TYPES statements within the statements BEGIN OF and END OF define the components of the structured type struc_type. If a component is a structured type or if a new structured type is defined within a structure using BEGIN OF and END OF, substructures are created. A structure with substructures is known as a nested structure.
A component of struc_type cannot be declared with reference to struc_type itself . If the name struc_type is specified after TYPE in the declaration of a component, a search is performed for the next type with this name in a higher visibility section, and used if found. If a more global type with this name does not exist, a syntax error occurs.
If a component is created as a table type, this type cannot be generic.
The statement INCLUDE defines components of the structured type struc_type by using the components of a differently structured type or an existing structure at the same level.
The components of a structured type are divided using the name struc_type and the name of the component, and addressed using the structure component selector (-).
Notes
◈ The value operator VALUE can be used to construct the content of structures.
◈ A structure type is always fully specified. There is no generic structure type.
Example
This example defines two structured types, street_type and address_type. address_type contains structured types as components. The definition of zipcode_type shows the access to substructures.
TYPES: BEGIN OF street_type,
name TYPE c LENGTH 40,
no TYPE c LENGTH 4,
END OF street_type.
TYPES: BEGIN OF address_type,
name TYPE c LENGTH 30,
street TYPE street_type,
BEGIN OF city,
zipcode TYPE n LENGTH 5,
name TYPE c LENGTH 40,
END OF city,
END OF address_type.
TYPES zipcode_type TYPE address_type-city-zipcode.
1.4.1 TYPES - BOXED
Syntax
TYPES comp TYPE struc_type BOXED.
Effect
This statement defines a substructure comp of a structure as a static box. It can only be located within the associated structure definition with the additions BEGIN OF and END OF of the statement TYPES and only at the top component level and not within nested BEGIN OF ... END OF blocks.
struc_type expects a structured data type. This can be a program-local structure, a visible structured type of a class or of a global interface, or a structure from ABAP Dictionary, and can contain boxed components.
Static boxes support initial value sharing. Here, the structure is not saved in the higher level context itself. Instead, an internal reference that points to the actual structure is saved in place of the component. This makes a static box a deep component.
Notes
◈ A structure with a static box is a deep structure and the relevant restrictions apply.
◈ The addition BOXED defines the static box with reference to its context (structure or class). A data type declared using a direct TYPE reference or LIKE reference to a static box is assigned its data type but is not a static box itself.
◈ When a static box is transferred from one structure to another structure using the statement INCLUDE TYPE|STRUCTURE, its static attribute is also transferred.
◈ If a nested structure whose static boxes already contain static boxes needs to be created, this is only possible if each substructure in question exists as a standalone type. It is not possible to specify BOXED for substructures created by nestings using TYPES BEGIN OF ... TYPES END OF.
◈ The addition BOXED can also be used in the statement DATA to declare a structured attribute of a class or an interface.
Example
The following section shows how the addition BOXED can be used with the statement TYPES. In a structured type t_struc2, a substructure t_struc2-comp2 of type t_struc1 is declared as a static box.
TYPES: BEGIN OF t_struc1,
comp1 TYPE c LENGTH 100,
comp2 TYPE n LENGTH 100,
END OF t_struc1.
TYPES: BEGIN OF t_struc2,
comp1 TYPE string,
comp2 TYPE t_struc1 BOXED,
END OF t_struc2.
1.4.2 INCLUDE - TYPE, STRUCTURE
Syntax
INCLUDE { {TYPE struc_type} | {STRUCTURE struc} }
[AS name [RENAMING WITH SUFFIX suffix]].
Additions
1. ... AS name
2. ... RENAMING WITH SUFFIX suffix
Effect
This statement can only be declared within a structure definition with the additions BEGIN OF and END OF of the statements TYPES, DATA, CLASS-DATA, and STATICS. It copies all the components of the structured type struc_type or the structure struc at the specified location to the current structure definition. The INCLUDE statement does not create a substructure, which means the components are inserted as if they are included individually in place of the statement INCLUDE.
struc_type can be a local structured type, a visible structured type of a global class or global interface, or a structure from ABAP Dictionary. struc must be a structure of the same program or a visible attribute of a global class or global interface.
Notes
- The statement INCLUDE described here should no longer be used for the following reasons:
- If further structure components are to be added to existing components using the statement INCLUDE or if multiple INCLUDE statements are used in a structure, this can produce syntax errors due to naming conflicts. This is particularly problematic if structures that are not defined in the same program are included and these are to be changed at a later date.
- The included structures cannot be addressed as such without restrictions.
- The necessary metadata is stored again for each component of an included structure, whereas the metadata for the components of a substructure is only stored once when the substructure is defined.
- In contrast to real substructures, structures included using INCLUDE cannot be declared as static boxes when embedded.
- Where possible, real substructures should be created rather than using the statement INCLUDE. The addition RENAMING WITH SUFFIX, however, should be used to prevent naming conflicts. This recommendation also applies to includes of structures in ABAP Dictionary, where the structures of database tables in particular cannot contain any real substructures.
- Outside of ABAP objects, flat structures, database tables, or views in ABAP Dictionary can also be specified for struc with the addition STRUCTURE.
- In constant structures defined with CONSTANTS, no components can be included using INCLUDE because these cannot be assigned a start value.
- With respect to their alignments, structures included using INCLUDE behave like substructures, which means alignment gaps can occur before the first or after the last component. These do not occur when the components are declared directly.
- A structure that is included using INCLUDE is handled by method GET_COMPONENTS of class CL_ABAP_STRUCTDESCR of RTTI in the same way as a substructure. The returned component table only contains one row for an included structure. The component type is represented by an object from CL_ABAP_STRUCTDESCR, but the AS_INCLUDE column contains the value "X". The method GET_INCLUDED_VIEW_TAB can be used to resolve the components of included structures.
- When a static box is copied from one structure to another, its boxed component attribute is also copied.
Addition 1
... AS name
Effect
By specifying the name name after the addition AS, either all components of the included structure struc_type or struc can be addressed together using the name name, or individual components can be addressed using the structure component selector (-). The name name must be unique within the structure in which the components are included. This means that there can be no other component with this name and it cannot be specified in a different INCLUDE statement after AS.
Notes
Included components for which a name is specified after AS can be addressed in the same way as if they were components of a substructure name.
A name name specified with AS name is used only as an addressing option and is ignored in statements such as MOVE-CORRESPONDING or SELECT INTO CORRESPONDING. A component renamed using RENAMING WITH SUFFIX actually has this name and is therefore not ignored.
Addition 2
... RENAMING WITH SUFFIX suffix
Effect
With the addition RENAMING WITH SUFFIX, each individual component is renamed by adding the extension suffix, which prevents naming conflicts between components of the same name. suffix must be specified directly.
Note
The addition RENAMING WITH SUFFIX can be used to include an individual structure multiple times.
Example
In this example, the structure week is defined by repeatedly using the components of the structured type t_day. The components of week are all at the same level and can be addressed as follows: week-work_mon, week-free_mon, week-work_tue, and so on. Alternatively, they can also be addressed as follows: week-monday-work, week-monday-free, week-tuesday-work, and so on.
TYPES: BEGIN OF t_day,
work TYPE c LENGTH 8,
free TYPE c LENGTH 16,
END OF t_day.
DATA BEGIN OF week.
INCLUDE TYPE t_day AS monday RENAMING WITH SUFFIX _mon.
INCLUDE TYPE t_day AS tuesday RENAMING WITH SUFFIX _tue.
INCLUDE TYPE t_day AS wednesday RENAMING WITH SUFFIX _wed.
...
DATA END OF week.
1.5 TYPES - TABLE OF
Syntax
TYPES table_type { {TYPE tabkind OF [REF TO] type}
| {LIKE tabkind OF dobj} }
[tabkeys]
[INITIAL SIZE n].
Addition:
... INITIAL SIZE n
Effect
This statement defines a table type table_type with a specific row type, a table category tabkind, and table keys tabkeys.
The row type is determined by entering the data type type after TYPE and data type dobj after LIKE:
◈ type can be a non-generic data type from ABAP Dictionary, a non-generic public data type of a public data type or global class, a non-generic data type local to a program, or any ABAP type from the tables of predefined ABAP types. The generic ABAP types c, n, p, and x are implicitly extended to the standard length without decimal places from the tables of predefined ABAP types.
If the addition REF TO is specified before type or dobj, the row type is a reference type. The information specified in section reference types can then be entered for type and dobj.
◈ The same applies to dobj as to TYPES ... LIKE.
Note: The use of the addition OCCURS for defining table types is obsolete.
1.5.1 TYPES - tabkind
Syntax
... { {[STANDARD] TABLE}
| {SORTED TABLE}
| {HASHED TABLE}
| {ANY TABLE}
| {INDEX TABLE} } ...
Effect
Defines the table category of an internal table.
It is possible to specify the non-generic table categories standard table (STANDARD TABLE), sorted table (SORTED TABLE), and hashed table (HASHED TABLE), as well as the generic table categories ANY TABLE and INDEX TABLE. The addition STANDARD is optional for standard tables.
The non-generic table categories specify the internal administration and primary access type for an internal table in ABAP programs:
◈ Standard tables are managed-internally in the system by using a primary table index. New rows are either appended to the table or inserted at specific positions.
◈ Like standard tables, sorted tables are also managed using a primary table index. The entries in this index are always sorted in ascending order by the primary table key. The sort order is in ascending order and returns the same result as the statement SORT with no additions.
◈ Hashed tables are managed by a hash algorithm. There is no primary table index. The entries are not ordered in the memory. The position of a row is calculated by specifying a key using a hash function.
The generic table categories define a generic table type that can only be used for typing formal parameters and field symbols:
◈ ANY TABLE covers all table categories
◈ INDEX TABLE covers standard tables and sorted tables
Notes
◈ For non-generic table categories, the definition of the table key key determines whether the defined table type is generic.
◈ The additions of the statement TYPES listed above are language element additions for defining table categories. They are not to be confused with the generic ABAP types with the same name.
◈ A generic table type cannot be used as a component of a structured type.
1.5.2 TYPES - tabkeys
Syntax
... [ WITH key ]
[ WITH secondary_key1 ] [ WITH secondary_key2 ] ...
[ {WITH|WITHOUT} FURTHER SECONDARY KEYS ] ...
Additions
1. ... WITH FURTHER SECONDARY KEYS
2. ... WITHOUT FURTHER SECONDARY KEYS
Effect
Defines the table key of a table type. The following can be defined:
◇ A primary table key using key.
◇ Up to 15 secondary table keys using secondary_key1, secondary_key2, ....
The order in which the components of a table key are defined is significant for the table type. The additions WITH|WITHOUT FURTHER SECONDARY KEYS determine the genericness with respect to the secondary table key.
An internal table that has no table key or an incomplete table key is generic with respect to the table key. A table type of this nature can be used only for typing formal parameters or field symbols. For DATA, a standard table type with a generic primary table key can be specified after TYPE. In this case, a bound table type with a standard key is created.
Primary Key
The genericness of a table type with respect to the primary key is determined as follows:
◇ If WITH key is not specified, a table type is generic with respect to the primary key.
◇ If a declaration about the uniqueness of the key is not made in key, a table type is partly generic with respect to the key.
◇ If a key declaration with a uniqueness declaration is made in key, a table type is not generic with respect to the primary key.
The non-generic table categories can be split up as follows:
◇ If no primary key is declared for standard tables, this primary key is generic with respect to the key fields and defined implicitly as non-unique.
◇ If no primary key is declared for sorted tables, this primary key is generic with respect to the key fields and uniqueness.
◇ If no primary key is declared for hashed tables, this primary key is generic with respect to the key fields and uniqueness; note, however, that fixed hashed tables can have only one unique key.
Secondary Key
The genericness of a table type with respect to the secondary key depends (by default) on the genericness of the primary key and can be overridden using the additions WITH|WITHOUT FURTHER SECONDARY KEYS.
◇ If the primary key is fully or partly generic, the table type is by default generic with respect to the secondary key. The default behavior can be expressed using the addition WITH FURTHER SECONDARY KEYS. However, if the addition WITHOUT FURTHER SECONDARY KEYS is specified, the table type is generic with respect to the primary key but not with respect to the secondary key.
◇ If the primary key is not generic, the table type is not generic with respect to the secondary key either (by default). The default behavior can be expressed using the addition WITHOUT FURTHER SECONDARY KEYS. If, however, WITH FURTHER SECONDARY KEYS is declared, the table type is generic with respect to the secondary key but not with respect to the primary key.
Note
A generic table type cannot be used as a component of a structured type.
Addition 1
... WITH FURTHER SECONDARY KEYS
Effect
This addition defines the table type explicitly as being generic with respect to the secondary key. This means it includes table types that can have further secondary keys and not just the optional secondary keys declared using WITH secondary_key ....
If 15 secondary keys are already defined, the addition WITH FURTHER SECONDARY KEYS cannot be specified.
Addition 2
... WITHOUT FURTHER SECONDARY KEYS
Effect
This addition defines the table type explicitly as being non-generic with respect to the secondary key. This means it includes only those table types that have those secondary keys specified using WITH secondary_key ....
◐ TYPES - key
Syntax
... { [UNIQUE | NON-UNIQUE]
{ {KEY [primary_key [ALIAS key_name] COMPONENTS] comp1 comp2 ...}
| {DEFAULT KEY} } }
| { EMPTY KEY } ...
Alternatives:
1. ... [UNIQUE|NON-UNIQUE] {KEY ...}|{DEFAULT KEY}
2. ... EMPTY KEY
Alternative 1
... [UNIQUE|NON-UNIQUE] {KEY ...}|{DEFAULT KEY}
Additions
1. ... primary_key COMPONENTS
2. ... ALIAS key_name
Effect
Defines the primary table key of an internal table by specifying components or as a standard key.
Name of the Primary Key
Like secondary keys, the primary key also has a name with which it is addressed. This name cannot be freely selected and is predefined as "primary_key". It does not have to be explicitly specified when the table is defined since it is always set implicitly. However, it can also be specified before the addition COMPONENTS.
Key Fields
The key fields of the primary key can be defined in the following ways; the order is significant:
◈ Individual components comp1 comp2 ... of the row type are specified after KEY. The row type must be structured and the components cannot be table types and cannot contain table types as components. For elementary row types, table_line is the only component that can be specified.
◈ If the whole table row is to be defined as a key, the pseudo component table_line can be declared as the only component comp after KEY. This is possible for all row types that are not table types or that do not contain table types as components. For structured row types, table_line operates like a listing of each individual component.
◈ Specifying the standard key DEFAULT KEY. The standard key fields of a structured row type are all fields with non-numeric elementary data type. The standard key for non-structured row types is the entire table row, if the row type itself is not a table type. If there is no corresponding component or if the row type is itself a table type, the standard key is empty – this applies to standard tables only.
The key fields of the primary table key are generally read-only in all operations that change the content of individual rows of a sorted table or hashed table.
Uniqueness of the Primary Key
The UNIQUE or NON-UNIQUE declarations specify the uniqueness of the primary table key. In the case of a primary table key specified with UNIQUE, a row with specific content of the key fields can appear only once in an internal table of this type. Only NON-UNIQUE can be used for standard tables; UNIQUE must be used for hashed tables; both can be declared for sorted tables.
◈ The uniqueness declaration can be omitted, which makes the table type partially generic with respect to the primary key declaration. The table type can then only be used for typings of formal parameters or field symbols. The differences between the table categories are as follows:
◈ The addition NON-UNIQUE is expanded implicitly in the case of types for standard tables. A standard table is never generic with respect to uniqueness.
◈ Types for sorted tables can be completely generic with respect to uniqueness.
◈ Types for hashed tables can be completely generic with respect to uniqueness; a fixed hashed table, however, always has a unique primary key.
◈ No uniqueness declaration can be made for the generic table categories ANY TABLE or INDEX TABLE.
Notes
◈ The declaration of the primary table key as a standard key can be critical for various reasons. It is best to specify key fields explicitly instead.
◈ Structured components in particular can be explicitly specified as key fields, provided that the components meet the other requirements. When a structured key field is evaluated, the rules for structure comparisons apply.
◈ Note that the addition DEFAULT KEY must not be confused with the addition EMPTY KEY. A standard key declared using the addition DEFAULT KEY can be empty unexpectedly in a standard table, whereas EMPTY KEY declares empty primary table keys explicitly for tables with any row types.
◈ Static boxes and their components can be key fields of internal tables.
Example
Defines a primary key without an explicitly specified name. The statement has the same meaning as in the following example.
TYPES sbook_tab
TYPE SORTED TABLE
OF sbook
WITH UNIQUE KEY carrid connid fldate bookid.
Addition 1
... primary_key COMPONENTS
Effect
If the key fields are defined by specifying components, the name of the primary key can be specified explicitly in the statement TYPES. However, the predefined name "primary_key" must be specified for primary_key. The addition COMPONENTS must then also be specified before the component is specified.
Note
Explicitly specifying the name primary_key does not enable predefined name "primary_key" to be changed, but does enable an alias name to be specified by using the addition ALIAS.
Example
Defines a primary key with an explicitly specified name. The statement has the same meaning as in the previous example.
TYPES sbook_tab
TYPE SORTED TABLE
OF sbook
WITH UNIQUE KEY primary_key
COMPONENTS carrid connid fldate bookid.
Addition 2
... ALIAS key_name
Effect
An alias name key_name can be defined for the primary key when using sorted tables and hashed tables, as long as the primary key is not generic. The alias name is in the namespace of the secondary key, must comply with the naming conventions, and must be unique. It enables the primary key to be addressed like a secondary key by means of a self-defined name.
The syntax requires the name primary_key to also be declared explicitly in the definition of the alias name.
Alternative 2
... EMPTY KEY
Effect
Defines an empty primary key of a table type. This variant is possible for standard tables only. An empty table key does not contain any key fields.
Notes
◈ When an empty table key is defined explicitly, this means that the internal table is to be handled like an array that is not subject to being ordered by key values.
◈ The ordering of a standard table with an empty primary key is determined for the most part by the primary index. There are no restrictions on related index accesses and loop processing.
◈ In statements that evaluate the primary table key to identify rows, an empty table key generally produces unexpected behavior and a syntax check warning. For a list of these statements, see Empty Table Key.
◈ A table key where EMPTY KEY is used to declare an empty table key explicitly is not generic with respect to its primary key. This means that the addition EMPTY KEY can be used to prevent a table type from being too generic with respect to its primary key.
◈ The explicit declaration of an empty table key using EMPTY KEY is independent of the row type.
◈ A standard table with an empty primary key can have non-empty secondary keys.
◈ Empty table keys can also be created implicitly when the standard key is used for standard tables. If an empty table key is to be used, however, it is better to declare it explicitly using EMPTY KEY.
Example
The table in the example below is only intended for a loop in which all rows of the table are processed in a random order.
TYPES addresses TYPE STANDARD TABLE OF scustom-email WITH EMPTY KEY.
DATA email_tab TYPE addresses.
FIELD-SYMBOLS <email> LIKE LINE OF email_tab.
...
SELECT email
FROM scustom
INTO TABLE @email_tab.
...
LOOP AT email_tab ASSIGNING <email> USING KEY primary_key.
mail_manager->send( address = <email> text = ... ).
ENDLOOP.
◐ TYPES - secondary_key
Syntax
... {UNIQUE HASHED}|{UNIQUE SORTED}|{NON-UNIQUE SORTED}
KEY key_name COMPONENTS comp1 comp2 ...
Effect
Defines a secondary table key with an internal table type. An internal table can have up to 15 secondary keys.
Types of Secondary Keys
Secondary keys are split into three types based on the type of access and their uniqueness:
◈ Unique secondary hash keys defined with UNIQUE HASHED that are linked to table rows using a hash algorithm
◈ Unique secondary sorted keys defined with UNIQUE SORTED that are linked to table rows using a secondary table index (in which the key fields are sorted in ascending order)
◈ Unique secondary sorted keys defined with UNIQUE SORTED that are linked to table rows using a secondary table index (in which the key fields are sorted in ascending order).
Names of Secondary Keys
Each secondary key has a unique name with which it can be addressed. The name must be specified directly as key_name and must comply with the naming conventions. The name specified cannot be one of the predefined names primary_key or loop_key. In addition, the names of secondary keys and any alias name used for the primary key must be unique.
Key Fields
The key fields of the secondary key can be defined in the following ways; the order is significant:
◈ Individual components comp1 comp2 ... of the row type are specified after KEY. The row type must be structured and the components cannot be table types and cannot contain table types as components.
◈ If the whole table row is to be defined as a key, the pseudo component table_line can be declared as the only component comp after KEY. This is possible for all row types that are not table types or that do not contain table types as components.
In an operation that changes the content of individual rows of an internal table, the key fields of a secondary table key are read-only only if the secondary key is used during this operation.
Notes
◈ When internal tables are accessed with the statements READ TABLE itab, LOOP AT itab, MODIFY itab and DELETE itab or in reads using table expressions and in mesh types and mesh paths, a secondary key can be used to specify the rows to be processed or the processing order. To do this, the additions WITH [TABLE] KEY ... COMPONENTS or USING KEY must be specified.A secondary key is never used implicitly.
◈ The statement INSERT itab determines the insert position using the primary key and primary index only. A secondary key can be specified only for the source table from which multiple rows are copied. The latter also applies to the statement APPEND.
◈ A secondary key is never generic. When it is defined, all secondary fields and the uniqueness must be specified fully. An internal table type can, however, be generic with respect to its number of secondary keys.
◈ DEFAULT KEY cannot be declared for secondary keys.
◈ Structured components in particular can be specified as key fields, provided that the components meet the other requirements. When a structured key field is evaluated, the rules for structure comparisons apply.
◈ If different table keys for an internal table contain the same components, the syntax check issues a warning (which can be hidden using a pragma).
◈ With the exception of the restrictions outlined above, the names of secondary keys can be chosen as wanted, but the component names of the internal table must not be used. The name loop_key is reserved for the explicit declaration of the key used for LOOP processing.
◈ The internal management of secondary keys in an internal table can involve significant memory consumption and updates. For this reason, secondary keys should be used sparingly and only implemented if their benefits outweigh the costs. See, for example, Deleting Rows Using Keys.
Example
Defines a table type with a primary key and two secondary keys hash_key and sort_key. The primary key in a standard table cannot be unique. The secondary key hash_key has the same components as the primary key and must be a unique hash key. The sorted key sort_key could also be defined as unique, but this is not beneficial in the example shown here, since a customer ID can appear more than once in the reservation table.
TYPES sbook_tab
TYPE STANDARD TABLE
OF sbook
WITH NON-UNIQUE KEY primary_key
COMPONENTS carrid connid fldate bookid
WITH UNIQUE HASHED KEY hash_key
COMPONENTS carrid connid fldate bookid
WITH NON-UNIQUE SORTED KEY sort_key
COMPONENTS customid.
Example
The DEMO_SECONDARY_KEYS program demonstrates the declaration and use of a secondary table key and the resulting performance gains.
This example demonstrates how nested internal tables are declared and used.
Source Code
REPORT demo_nested_internal_tables.
CLASS table_demo DEFINITION.
PUBLIC SECTION.
CLASS-METHODS main.
PRIVATE SECTION.
TYPES:
BEGIN OF t_address,
street TYPE c LENGTH 20,
city TYPE c LENGTH 20,
END OF t_address,
t_address_tab TYPE STANDARD TABLE
OF t_address
WITH NON-UNIQUE KEY city.
CLASS-DATA:
BEGIN OF company,
name TYPE c LENGTH 20,
addresses TYPE t_address_tab,
END OF company,
company_tab LIKE HASHED TABLE
OF company
WITH UNIQUE KEY name,
company_sorted_tab LIKE SORTED TABLE
OF company
WITH UNIQUE KEY name.
ENDCLASS.
CLASS table_demo IMPLEMENTATION.
METHOD main.
DATA: address TYPE t_address,
idx TYPE sy-tabix,
output TYPE c LENGTH 80.
FIELD-SYMBOLS <fs> LIKE company.
DATA(out) = cl_demo_output=>new( ).
* Filling Internal Tables
company_tab = VALUE #(
( name = 'Racing Bikes Inc.'
addresses = VALUE #( ( street = 'Fifth Avenue'
city = 'New York' )
( street = 'Second Street'
city = 'Boston' ) ) )
( name = 'Chocolatiers Suisse'
addresses = VALUE #( ( street = 'Avenue des Forets'
city = 'Geneve' )
( street = 'Kleine Bachgasse'
city = 'Basel' )
( street = 'Piazza di Lago'
city = 'Lugano' ) ) ) ).
* Reading Internal Tables
READ TABLE company_tab
WITH TABLE KEY name = 'Racing Bikes Inc.'
ASSIGNING <fs>.
out->write( |{ <fs>-name }| ).
LOOP AT <fs>-addresses INTO address.
CLEAR output.
WRITE: sy-tabix TO output+4(4),
address-street TO output+8(20),
address-city TO output+28(20).
out->write( output ).
ENDLOOP.
* Modifying Internal Tables
address-street = 'Rue des Montagnes'.
address-city = 'Geneve'.
READ TABLE company_tab
WITH TABLE KEY name = 'Chocolatiers Suisse'
INTO company.
READ TABLE company-addresses TRANSPORTING NO FIELDS
WITH TABLE KEY city = address-city.
idx = sy-tabix.
MODIFY company-addresses FROM address INDEX idx.
MODIFY TABLE company_tab FROM company.
* Moving and sorting Internal Tables
company_sorted_tab = company_tab.
LOOP AT company_sorted_tab INTO company.
out->write( |{ company-name }| ).
SORT company-addresses.
LOOP AT company-addresses INTO address.
CLEAR output.
WRITE: sy-tabix TO output+4(4),
address-street TO output+8(20),
address-city TO output+28(20).
out->write( output ).
ENDLOOP.
ENDLOOP.
* text output
out->display( ).
ENDMETHOD.
ENDCLASS.
START-OF-SELECTION.
table_demo=>main( ).
Description
The example shows the declaration of two internal tables t_address_tab and company_tab, where t_address_tab is contained in company_tab. For this purpose t_address_tab is defined as the table type. The component addresses of the company structure is declared with this type. The data type of company is used as the row type for the tables company_tab and company_sorted_tab.
The internal table is filled using the value operator VALUE.
A row from company_tab is assigned to the field symbol <fs> using READ and its table-like component addresses is processed in a LOOP. The content of the row is assigned to the structure address. Since addresses is an index table, sy-tabix can be analyzed.
To change the content of the component street of a row of the inner table addresses, the index of the relevant row is determined using a READ statement and it is then used in MODIFY. To make the changes effective in the corresponding row of the outer hashed table as well, the key access of the MODIFY statement is used.
Finally, the hashed table is assigned a sorted table with the same row type. In this way, the entries are automatically sorted by the table key name. However, the entries of the inner standard table are sorted using the SORT command.
1.6 TYPES - RANGE OF
Syntax
TYPES dtype {TYPE RANGE OF type}|{LIKE RANGE OF dobj}
[INITIAL SIZE n].
Effect
Derives a table type for a ranges table. A ranges table is a standard table with a standard key and a specially structured row type whose internal definition can be displayed as follows in ABAP syntax:
TYPES: BEGIN OF linetype,
sign TYPE c LENGTH 1,
option TYPE c LENGTH 2,
low {TYPE type}|{LIKE dobj},
high {TYPE type}|{LIKE dobj},
END OF linetype.
The additions TYPE and LIKE determine the data type of the components low and high:
◈ type can be a non-generic data type from ABAP Dictionary, a non-generic public data type of a public data type or global class, a non-generic data type local to a program, or any ABAP type from the tables of predefined ABAP types. The generic ABAP types c, n, p, and x are expanded implicitly to the standard length without decimal places from the tables of predefined ABAP types.
◈ dobj can be a data object visible at this point, whose type is used for both components. Generically typed formal parameters cannot be specified for dobj within a procedure.
The addition INITIAL SIZE is synonymous with the definition of normal internal table types.
Notes
◈ A ranges table has the same structure as a selection table, and can be used to pass values to the selection screens of an executable program called using SUBMIT in a comparison expression with the relational operator IN or in a similar expression in a WHERE condition in Open SQL.
◈ The sign and option columns of a ranges table declared using RANGE OF are not related to data types in ABAP Dictionary. For a ranges table defined in ABAP Dictionary, these columns are based on the data elements DDSIGN and DDOPTION.
1.7 TYPES - CLIENT SPECIFIED
Syntax
TYPES dtype TYPE cds_entity CLIENT SPECIFIED clnt.
Effect
The statement TYPES uses the addition CLIENT SPECIFIED to define a structured type constructed from all components of a CDS entity cds_entity and that also has an initial component clnt with the type of a client column.
cds_entity expects the name of a CDS entity, namely:
The name of a CDS view as defined in the CDS DDL statement DEFINE VIEW.
The name of a CDS table function as defined in the CDS DDL statement DEFINE TABLE FUNCTION.
Any name for the client column that complies with the naming conventions can be specified for clnt.
Notes
◈ A structure of a type defined using this statement can be used as a work area of a SELECT statement for CDS entities in which automatic client handling is switched off using CLIENT SPECIFIED.
◈ The name specified for clnt has absolutely no dependency on the actual name of a client column in a data source of a CDS view.
Syntax
TYPES BEGIN OF MESH mesh_type.
...
TYPES node { TYPE {[REF TO] table_type}|ref_type }
| { LIKE {[REF TO] itab }|dref }
[ association1],
[association2],
...
...
TYPES END OF MESH mesh_type.
Effect
Defines a mesh type for a mesh. A mesh type is a special structure type. The components of the structure type are referred to as mesh nodes and are subject to the following restrictions:
◈ The type of a mesh node must be a non-generic table type or a reference type with the static type of a non-generic internal table. The node type can be defined as follows:
◈ With the addition TYPE while specifying a table type table_type with or without REF TO or while specifying a reference type ref_type of this kind directly.
◈ With the addition LIKE while specifying an internal table itab with or without REF TO or while specifying a reference variable dref of this kind directly.
◈ The row type of a mesh node must be structured and cannot contain any internal tables or reference variables. Elementary data types and substructures are permitted as components. Substructures must meet the same prerequisite.
A normal structure type can be enhanced by defining one or more associations association for every mesh node. These associations link two mesh nodes using a condition. The relationships between the tabular nodes of a mesh type defined using associations are evaluated in the special expressions and statements used to process meshes in mesh paths.
Notes
◈ Meshes must be fully compatible for assignments, comparisons, and parameter passing. Meshes are compatible when their structures are compatible, the node names match, and the associations match with respect to name ON conditions and the table key used.
◈ Using the structure component selector (-), mesh nodes can be addressed and used like the components of the corresponding structure If field symbols or reference variables point to mesh nodes, they are also handled like regular structure components. In particular, the statement MOVE-CORRESPONDING can also be used between incompatible meshes and between meshes and structures.
◈ A mesh type is always fully defined. Generic mesh types are not possible.
◈ It is a particularly good idea to use reference types as components when meshes are injected into existing programs with suitable internal tables.
Example
Declares a mesh type with internal tables for the flight data model.
TYPES:
BEGIN OF MESH t_flights,
scarr TYPE t_scarr
ASSOCIATION to_spfli TO spfli
ON carrid = carrid USING KEY carrid,
spfli TYPE t_spfli
ASSOCIATION to_sflight TO sflight
ON carrid = carrid AND
connid = connid USING KEY carrid_connid
ASSOCIATION to_sairport TO sairport
ON id = airpfrom,
sflight TYPE t_sflight,
sairport TYPE t_sairport,
END OF MESH t_flights.
1.8.1 TYPES - association
Syntax
... ASSOCIATION _assoc TO node ON tcomp1 = scomp1
[AND tcomp2 = scomp2
[AND ... ]]
[USING KEY key_name] ...
Additions
1. ... ON tcomp1 = scomp1 [AND tcomp2 = scomp2 [AND ... ]]
2. ... USING KEY key_name
Effect
Defines an association named _assoc for a mesh node of a mesh type. Addition ASSOCIATION to TYPES can only be used in the definition of a mesh type between TYPES BEGIN OF MESH and TYPES END OF MESH. The mesh node, for which an association is defined, is the start node. The mesh node node specified after TO is the target node. Any node in the current mesh (including the start node) can be specified as the target node node. An association where the start node and target node are the same is referred to as a reflexive association.
The name of an association cannot be longer than 30 characters. It can only contain the letters A-Z, the digits 0-9, and the underscore "_" character, and cannot begin with a digit.
Notes
◈ The associations defined for a mesh node are evaluated in expressions and statements for meshes in mesh paths.
◈ It is not mandatory to define a target node before the start node to make the target node visible. However, the Code Completion function of the editor will only work properly if the target node is defined before the start node.
◈ The prefix _ is recommended as the naming convention for associations. The name that follows this prefix should contain the target node name (in non-reflexive associations). This convention makes it easier to read the mesh path.
Addition 1
... ON tcomp1 = scomp1 [AND tcomp2 = scomp2 [AND ... ]]
Effect
For every association, a condition must be specified after ON that consists of at least one comparison for equality. Additional comparisons for equality can be added using AND. The left operand tcomp of every comparison must be a directly specified column of the target node. The right operand scomp must be a directly specified column of the start node and this column must be compatible with the column of the target node.
An association represents the relationship between the start node and target node. It assigns all the rows of the target node that meet the condition to a row of the start node.
The associations are type-only attributes and therefore affect the compatibility of mesh types. Associations are evaluated in mesh paths in expressions and in statements for meshes.
Notes
◈ In the ON condition, the target node components are on the left and the start node components are on the right. This is the same as in other statements and expressions for internal tables, where the columns of the table to be searched are always specified on the left.
◈ As a general rule, the target node components specified on the left of an ON condition should be key fields of the table key used for the condition. This ensures the best possible system performance when accessing data.
Addition 2
... USING KEY key_name
Effect
Using the addition USING KEY, a table key of the target node can be specified for the ON condition of an association. The target node is the one used in expressions and statements to evaluate meshes for accessing the mesh node:
◈ a secondary key using its name
◈ a primary key using its predefined name primary_key or using an alias. If the primary key is specified, the target node must be a sorted table or a hashed table.
The name of the table key must be specified directly. In other words, it cannot be dynamically specified in a data object. If the table key is explicitly specified, the ON condition must be defined to allow optimal key access.
◈ If a sorted key or the primary key is specified, the conditions specified after ON must cover an initial left part of the key fields in the target table.
◈ If a secondary hash key or a primary key of a hashed table is specified, the conditions specified after ON must cover all key fields in the target table.
If addition USING KEY is not specified, the primary key is used to access the mesh node, which means that access is not always optimal.
Note
When the association is used in a mesh path, the table key specified in the definition of the ON condition can be overridden by specifying USING KEY in an additional condition. In this case, the ON condition and the additional condition are combined to make one single condition, which must meet the above prerequisites.
1.9 TYPES - LOB HANDLE
Syntax
TYPES dtype TYPE dbtab|view
lob_handle_type FOR lob_handle_columns
[ lob_handle_type FOR lob_handle_columns
... ].
Effect
Derives an LOB handle structure as a work area for working with streaming and locators in Open SQL. dbtab expects a database table defined in ABAP Dictionary or a database view defined for view in ABAP Dictionary.
The columns lob_handle_columns, when specified, are used to determine LOBs from dbtab. The statement creates a deep structure which is constructed exactly the same for all columns not included in the specified columns as it is for a regular TYPE reference to dbtab. For the LOBs included in the specified columns, a component with the same name is created as a LOB handle component. The static type of the LOB handle components is a class or an interface which is determined by the specified type lob_handle_type, and is assigned to the respective specified column.
The combinations of the additions specified under lob_handle_columns and lob_handle_type are determined using the following rules:
◈ An LOB handle structure can be derived for either reading or writing Open SQL statements only.
◈ A structure for reads can only contain the specified types READER, LOCATOR, and LOB HANDLE.
◈ A structure for writes can only contain the specified types WRITER and LOCATOR.
◈ The definition of the LOB handle components must not contain contradictions, which means that columns must not be assigned to unsuitable types or a column cannot be assigned to multiple types.
◈ The definition of LOB handle components must not contain redundancies. Each specified
... lob_handle_type FOR lob_handle_columns ...
must create a set of LOB handle components that do not overlap with another specified set of LOB handle components.
◈ The definition of the LOB handle components must be specified with as few components as possible. If the same set of LOB handle components can be specified once rather than using multiple input, the more comprehensive option must be used.
Apart from the rules specified under lob_handle_columns and lob_handle_type, there are also the following general restrictions:
◈ At least one column must be specified.
◈ The types specified for the first three specified column for LOB handle components for reads and the first two columns for LOB handle components for writes cannot be the same.
◈ In each case there can only be one column specified ALL ... COLUMNS, in which BLOB or CLOB are specified.
◈ The specified columns ALL BLOB|CLOB COLUMNS include all BLOBs or CLOBs. If they are specified, an individual BLOB or CLOB cannot also be specified in a specified column COLUMNS ... for the same static type.
◈ The specified columns ALL OTHER COLUMNS include all columns that are not specified individually. ALL OTHER BLOB COLUMNS or ALL OTHER CLOB COLUMNS cannot be specified at the same time.
◈ The specified columns ALL COLUMNS include all LOBs and can therefore only be specified on their own.
Notes
◈ LOB handle structures can also be defined using the corresponding typing of components between BEGIN OF and END OF.
◈ LOB handle structures can also be derived in ABAP Dictionary. The display of database tables or views containing LOBs includes a function for this.
◈ If dbtab does not contain any LOBs that match the specified columns, no LOB handle components are created and the statement creates a normal work area.
◈ If LOBs are added to dbtab that match the specified columns ALL [OTHER] ..., LOB handle components are also created for these.
1.9.1 TYPES - lob_handle_type
Syntax
... { READER|LOCATOR|{LOB HANDLE} }
| { WRITER|LOCATOR } ...
Effect
These additions define the static type of the LOB handle components when deriving a LOB handle structure using the statement TYPES.
- The addition READER defines the following:
- The static type CL_ABAP_DB_X_READER for BLOBs
- The static type CL_ABAP_DB_C_READER for CLOBs
- The addition WRITER defines the following:
- The static type CL_ABAP_DB_X_WRITER for BLOBs
- The static type CL_ABAP_DB_C_WRITER for CLOBs
- The addition LOCATOR defines the following:
- The static type CL_ABAP_DB_X_LOCATOR for BLOBs
- The static type CL_ABAP_DB_C_LOCATOR for CLOBs
- The addition LOB HANDLE defines the following:
- The static type IF_ABAP_DB_BLOB_HANDLE for BLOBs
- The static type IF_ABAP_DB_CLOB_HANDLE for CLOBs
The additions READER and WRITER cannot be used together in the statement TYPES. Furthermore, WRITER cannot be used with LOB HANDLE.
The combination options with the columns lob_handle_columns, when specified, are explained in the statement TYPES.
1.9.2 TYPES - lob_handle_columns
Syntax
... { COLUMNS blob1 blob2 ... clob1 clob2 ... }
| { ALL [OTHER] [BLOB|CLOB] COLUMNS } ...
Effect
These additions define which columns of the database table or the view dbtab are declared as LOB handle components when declaring a LOB handle structure using the TYPES statement.
◈ COLUMNS blob1 blob2 ... clob1 clob2 ...
specifies the individual BLOBs blob1, blob2, ... or the CLOBs clob1, clob2, .... These must exist in dbtab.
◈ ALL OTHER BLOB|CLOB COLUMNS
specifies all dbtab BLOBs or CLOBs which are not included when individual columns are specified. In the TYPES statement, at least one individual column, blob or clob, must be specified using COLUMNS ....
◈ ALL BLOB|CLOB COLUMNS
specifies all dbtab BLOBs or CLOBs.
◈ ALL OTHER COLUMNS
specifies all dbtab LOBs which are not included when individual columns are specified. In the statement TYPES, at least one individual column must be specified using COLUMNS ....
◈ ALL COLUMNS
specifies all LOBs of dbtab.
No other type of column specification can follow in the statement TYPES after columns specified using ALL OTHER ....
The different ways in which columns can be combined with each other and with the types specified using lob_handle_type are explained in the statement TYPES.
1.9.3 Deriving LOB Handle Structures
The example demonstrates the derivation of LOB handle structures using the TYPES statement.
Source Code
REPORT kellerh_test.
CLASS demo_lob_handles DEFINITION.
PUBLIC SECTION.
TYPES:
lob_handle_structure_1 TYPE demo_lob_table
READER FOR COLUMNS clob1 blob1,
lob_handle_structure_2 TYPE demo_lob_table
LOB HANDLE FOR ALL COLUMNS,
lob_handle_structure_3 TYPE demo_lob_table
LOCATOR FOR ALL BLOB COLUMNS
WRITER FOR ALL CLOB COLUMNS,
lob_handle_structure_4 TYPE demo_lob_table
READER FOR COLUMNS clob1 clob2
LOB HANDLE FOR ALL BLOB COLUMNS
LOCATOR FOR ALL OTHER CLOB COLUMNS,
lob_handle_structure_5 TYPE demo_lob_table
READER FOR COLUMNS blob1 blob2 blob3
LOCATOR FOR COLUMNS clob1 clob2 clob3
LOB HANDLE FOR ALL OTHER COLUMNS,
lob_handle_structure_6 TYPE demo_lob_table
READER FOR COLUMNS blob1
LOCATOR FOR COLUMNS blob2
LOB HANDLE FOR COLUMNS blob3
LOB HANDLE FOR ALL CLOB COLUMNS.
CLASS-METHODS main.
PRIVATE SECTION.
CLASS-DATA out TYPE REF TO if_demo_output.
CLASS-METHODS output_type IMPORTING struct TYPE string.
ENDCLASS.
CLASS demo_lob_handles IMPLEMENTATION.
METHOD main.
out = cl_demo_output=>new( ).
DO 6 TIMES.
output_type( |LOB_HANDLE_STRUCTURE_{ sy-index }| ).
ENDDO.
out->display( ).
ENDMETHOD.
METHOD output_type.
TYPES: BEGIN OF result,
component_name TYPE string,
absolute_name TYPE string,
END OF result,
results TYPE TABLE OF result WITH EMPTY KEY.
out->next_section( struct
)->write_data(
VALUE results(
FOR component IN CAST cl_abap_structdescr(
cl_abap_structdescr=>describe_by_name( struct )
)->components
WHERE ( type_kind = cl_abap_typedescr=>typekind_oref )
( VALUE #(
component_name = component-name
absolute_name = CAST cl_abap_refdescr(
cl_abap_typedescr=>describe_by_name(
struct && `-` && component-name )
)->get_referenced_type(
)->absolute_name ) ) ) ).
ENDMETHOD.
ENDCLASS.
START-OF-SELECTION.
demo_lob_handles=>main( ).
Description
The package-visible area of the demo_lob_handles class contains various derivations of LOB handle structures from the DEMO_LOB_TABLE database table. The methods of the class are used for the output of the static type of the derived LOB handle components.
The DEMO_LOB_TABLE database table contains a key field of type INT4, as well as three columns CLOB1, CLOB2, CLOB3 of type STRING and three columns BLOB1, BLOB2, BLOB3 of type RAWSTRING.
The derivations listed here function as follows:
◈ In the structured type lob_handle_structure_1, clob1 and blob1 become LOB handle components using direct column specification after READER. The component clob1 contains the static type CL_ABAP_DB_C_READER and blob1 contains the static type CL_ABAP_DB_X_READER. All other components are displayed according to the normal rules for their predefined types.
◈ In the structured type lob_handle_structure_2, all components are turned into LOB components by specifying FOR ALL COLUMNS for LOB handle components. The static type of the components of type STRING is IF_ABAP_DB_CLOB_HANDLE and the static type for the components of type RAWSTRING is IF_ABAP_DB_BLOB_HANDLE.
◈ In the structured type lob_handle_structure_3, all components are converted into LOB components for LOB handle components. The static type of the component of type STRING is converted into CL_ABAP_DB_C_WRITER by specifying WRITER FOR ALL CLOB COLUMNS and the static type for the components of type RAWSTRING is converted into CL_ABAP_DB_X_LOCATOR by specifying LOCATOR FOR ALL BLOB COLUMNS.
◈ In the structured type lob_handle_structure_4, all components are converted into LOB components for LOB handle components. The static type of the components clob1 and clob2 is converted into CL_ABAP_DB_C_READER by directly specifying READER. All components of the type RAWSTRING are converted into reference types for IF_ABAP_DB_BLOB_HANDLE by specifying LOB HANDLE FOR ALL BLOB COLUMNS. The other components of the type STRING are converted into reference types for CL_ABAP_DB_C_LOCATOR by specifying LOCATOR FOR ALL OTHER CLOB COLUMNS.
◈ In the structured type lob_handle_structure_5, all LOB components are listed directly and thereby converted into the corresponding LOB handle components with the static types CL_ABAP_DB_C_LOCATOR for clob1, clob2, and clob3 and CL_ABAP_DB_X_READER for blob1, blob2, and blob3. Specifying LOB HANDLE FOR ALL OTHER COLUMNS has no direct effect, but instead works on possible enhancements to the database table of further LOBs, which then preserve their appropriate interface reference type.
◈ In the structured type lob_handle_structure_6, all components are converted into LOB components for LOB handle components, whereby here the maximum number of column specifications is demonstrated. The specification of FOR ALL CLOB COLUMNS is only possible since no components of type STRING were recorded by the previous specifications.
1.1.3 Declaring Data Objects
A data object is an instance of a data type and occupies as much memory space as its type specifies. An ABAP program only works with data that is available as content of data objects. Data objects are either created implicitly in their declaration as named data objects or explicitly as anonymous data objects using CREATE DATA or the instance operator NEW.
- Data objects that are not declared using key words:
- Literals are data objects that are declared in operand positions using literal source code.
- Text symbols are character-like constant data objects that are declared outside the program.
- Declaration of variables and constants in every context:
- DATA
- CONSTANTS
- Declaration of static attributes in classes:
- CLASS-DATA
- Declaration of static variables in procedures:
- STATICS
- Declaration of interface work areas:
- TABLES
- NODES (obsolete)
⇰ Literals
Besides the named data objects which can be addressed by their names in the ABAP program (this includes the text symbols) and the anonymous data objects created by the statement CREATE DATA, there are literals which are defined in the source code of a program by specifying a string representing a value. Possible literals are:
◈ Numeric literals
◈ Character literals
The literal operator & can be used to associated multiple literals of the same type with each other.
1. Numeric Literals
Numeric literals consist of continuous sequences of numbers with a maximum of 31 digits (0 to 9), which can be directly preceded by a plus (+) or minus (-) sign.
◈ Numeric literals between -2147483648 and 2147483647 are integer literals and have the predefined ABAP type i.
◈ Numeric literals outside of this interval are packed numeric literals and have the predefined ABAP type p with a length of 8 bytes if they are not longer than 15 digits, and with a length of 16 bytes if they are between 16 and 31 digits long.
Notes
◈ There are no number literals of type int8. In order to convert a number literal int8, you can use the conversion operator CONV.
◈ In numeric literals, neither decimal separators nor scientific notation with mantissa and exponent are possible.
◈ Numbers that cannot be represented as numeric literals can only be specified in character literals. If used in operand positions where which a numeric value is expected, they are converted accordingly. The conversion operator CONV is recommended for targeted conversion.
◈ Numeric literals that span multiple lines are not permitted. Furthermore, the literal operator & cannot be used to create a composite literal from multiple numeric literals.
Example
The first literal has the type i. The following literals have the type p and lengths 8 and 16.
DATA: t TYPE c LENGTH 1,
l TYPE i.
DESCRIBE FIELD 123456 TYPE t.
cl_demo_output=>write( t ).
DESCRIBE FIELD 123456790123 TYPE t LENGTH l IN BYTE MODE.
cl_demo_output=>write( |{ t } { l }| ).
DESCRIBE FIELD 12345679012345678 TYPE t LENGTH l IN BYTE MODE.
cl_demo_output=>write( |{ t } { l }| ).
cl_demo_output=>display( ).
Example
Targeted conversion of a character literal into type int8.
DATA(num) = CONV int8( '123456790123' ).
2. Character Literals
Character literals can be either text field literals or text string literals. A text field literal is a character string enclosed in single quotation marks ('); a text string literal is a character string enclosed in single backquotes (`).
Syntax | Name | Possible Characters |
'...' | Text field literal | String of any alphanumeric characters. The data type is c with the length of the enclosed characters (including trailing blanks). The length of a text field literal must lie between 1 and 255 characters. There is no empty text field literal: The text field literal '' has the same meaning as the text field literal ' ' with length 1. To represent a quotation mark in a text field literal, two consecutive quotation marks must be specified. |
'...' | Text string literal | String of any alphanumeric characters. The data type is string. A text string literal can have a maximum of 255 characters. The empty text string literal `` represents an empty string with length 0. To represent a backquote in a text string literal, two consecutive backquotes must be specified. |
Character literals that span multiple lines are not allowed. The literal operator & can, however, be used to join multiple literals with the same type as a composite literal.
Trailing blanks are not ignored. If a text field literal is specified at an operand position at which a text symbol is possible, the three-character identifier idf of a text symbol can be appended in parentheses.
... 'Literal'(idf) ...
If the text symbol exists in the currently loaded text pool, the content of the text symbol is used instead of the literal, otherwise the literal is used. Text string literals cannot be associated with text symbols.
Notes
◈ Only text field literals (not text string literals) can be used to associate a literal with a text symbol.
◈ Trailing blanks in text field literals use memory, but are generally ignored in operand positions, like all data objects of the type c. In text string literals they are always relevant, as in all data objects of type string.
◈ Quotation marks can be represented directly in text string literals and backquotes in text field literals.
◈ The maximum length of the content of a character literal is 255 characters, which means that a literal with 255 characters cannot be specified within a single line of a program (due to the quotation marks or backquotes). The maximum length of 255 characters can be achieved only by using the literal operator &.
Example
Represents quotation marks and backquotes in character literals. The first two and the last two literals always have the same meaning.
cl_demo_output=>write_text( 'This is John''s bike' ).
cl_demo_output=>write_text( `This is John's bike` ).
cl_demo_output=>write_text( 'This is a backquote: `' ).
cl_demo_output=>write_text( `This is a backquote: ``` ).
cl_demo_output=>display( ).
3. Literal Operator
The literal operator & can be used to join two literals (of the same type) as a single literal. In this way, the definition of one literal can span multiple program lines. The content of the resulting literal must match its type and its length must not exceed the associated maximum length.
The literal operator can be used for the character literals, but not for the numeric literals. The syntax for text field literals and text string literals is:
'...' & '...' & ... & '...'
`...` & `...` & ... & `...`
These categories of literals cannot be mixed.
The literal operator can normally be used to join literals in any reading position. Exceptions to this are literals specified dynamically in parentheses, literals in parenthesized lists separated by commas (here the only relevant operand position is WHERE IN) and literals in embedded Native SQL.
Notes
◈ As well as for literals, the literal operator can also be used to join string templates.
◈ Any trailing blanks in text field literals are respected by the literal operator.
◈ When used for literals, the literal operator & must not be confused with the chaining operator && that can be used in string expressions to chain character-like operators. Whereas linking literals with the literal operator takes place once at the compilation of a program, the chaining operator executes a genuine operation at runtime and chains any number of character-like operands. The trailing blanks of operands with fixed lengths, in particular text field literals, are ignored.
◈ Character literals joined using the literal operator & are subject to the upper limit of 255 characters. Longer character strings can only be concatenated at runtime, for example, with the chaining operator &&.
Example
Constructs an HTML string from subliterals.
DATA html TYPE string.
html =
`<html>` &
`<body>` &
`Text` &
`</body>` &
`</html>`.
cl_abap_browser=>show_html( html_string = html )
The literal operator & can be used to join two literals (of the same type) as a single literal. In this way, the definition of one literal can span multiple program lines. The content of the resulting literal must match its type and its length must not exceed the associated maximum length.
The literal operator can be used for the character literals, but not for the numeric literals. The syntax for text field literals and text string literals is:
'...' & '...' & ... & '...'
`...` & `...` & ... & `...`
These categories of literals cannot be mixed.
The literal operator can normally be used to join literals in any reading position. Exceptions to this are literals specified dynamically in parentheses, literals in parenthesized lists separated by commas (here the only relevant operand position is WHERE IN) and literals in embedded Native SQL.
Notes
◈ As well as for literals, the literal operator can also be used to join string templates.
◈ Any trailing blanks in text field literals are respected by the literal operator.
◈ When used for literals, the literal operator & must not be confused with the chaining operator && that can be used in string expressions to chain character-like operators. Whereas linking literals with the literal operator takes place once at the compilation of a program, the chaining operator executes a genuine operation at runtime and chains any number of character-like operands. The trailing blanks of operands with fixed lengths, in particular text field literals, are ignored.
◈ Character literals joined using the literal operator & are subject to the upper limit of 255 characters. Longer character strings can only be concatenated at runtime, for example, with the chaining operator &&.
Example
Constructs an HTML string from subliterals.
DATA html TYPE string.
html =
`<html>` &
`<body>` &
`Text` &
`</body>` &
`</html>`.
cl_abap_browser=>show_html( html_string = html )
⇰ Text Symbols
A text symbol is a named data object of an ABAP program that is not declared in the program itself; instead, it is defined as a part of the text elements of the program. A text symbol has the data type c and the length defined in the text elements by mlen.
A text symbol behaves like a constant and can be specified in reading positions using the name text-idf. Here, idf is the three-character ID of the text symbol. This ID can consist of any alphanumeric characters plus "_". The text symbol is taken from the currently loaded text pool.
If the text symbol is not in the currently loaded text pool, text-idf is handled like an initial single-character text field. A text symbol can also be associated with the text field literals using the syntax 'Literal'(idf) and replaces these literals in the program, if the symbol is in the currently loaded text pool.
Notes
◈ Like all text elements, text symbols are linked to the translation environment. They can be used in all locations where translated texts are to be displayed by the program.
◈ The maximum length of a text symbol must be chosen so that there is enough space for the translation. For example, the English word "window" requires seven characters in German for "Fenster".
◈ The name text-idf is reserved for text symbols. A structure called text cannot have any components with three-character names. It is best never to call a structure text. This can cause syntax errors, in particular in structures that reference global data types.
A text symbol is a named data object of an ABAP program that is not declared in the program itself; instead, it is defined as a part of the text elements of the program. A text symbol has the data type c and the length defined in the text elements by mlen.
A text symbol behaves like a constant and can be specified in reading positions using the name text-idf. Here, idf is the three-character ID of the text symbol. This ID can consist of any alphanumeric characters plus "_". The text symbol is taken from the currently loaded text pool.
If the text symbol is not in the currently loaded text pool, text-idf is handled like an initial single-character text field. A text symbol can also be associated with the text field literals using the syntax 'Literal'(idf) and replaces these literals in the program, if the symbol is in the currently loaded text pool.
Notes
◈ Like all text elements, text symbols are linked to the translation environment. They can be used in all locations where translated texts are to be displayed by the program.
◈ The maximum length of a text symbol must be chosen so that there is enough space for the translation. For example, the English word "window" requires seven characters in German for "Fenster".
◈ The name text-idf is reserved for text symbols. A structure called text cannot have any components with three-character names. It is best never to call a structure text. This can cause syntax errors, in particular in structures that reference global data types.
⇰ DATA
Syntax Forms
Using Predefined Types
1. DATA { {var[(len)] TYPE abap_type [DECIMALS dec]}
| {var TYPE abap_type [LENGTH len] [DECIMALS dec]} }
[VALUE val|{IS INITIAL}]
[READ-ONLY].
Reference to Existing Types
2. DATA var { {TYPE [LINE OF] type}
| {LIKE [LINE OF] dobj} }
[VALUE val|{IS INITIAL}]
[READ-ONLY].
Reference Variables
3. DATA ref { {TYPE REF TO type}
| {LIKE REF TO dobj} }
[VALUE IS INITIAL]
[READ-ONLY].
Structures
4. DATA BEGIN OF struc [READ-ONLY].
...
DATA comp ...
INCLUDE {TYPE|STRUCTURE} ...
...
DATA END OF struc.
Internal Tables
5. DATA itab { {TYPE tabkind OF [REF TO] type}
| {LIKE tabkind OF dobj} }
[ tabkeys] [INITIAL SIZE n]
[WITH HEADER LINE]
[VALUE IS INITIAL]
[READ-ONLY].
Ranges Table
6. DATA rtab {TYPE RANGE OF type}|{LIKE RANGE OF dobj}
[INITIAL SIZE n]
[WITH HEADER LINE]
[VALUE IS INITIAL]
[READ-ONLY].
LOB Handle Structures
7. DATA dtype TYPE dbtab|view [READ-ONLY]
lob_handle_type FOR lob_handle_columns
[ lob_handle_type FOR lob_handle_columns
... ].
Static Boxed Components
8. DATA struc TYPE struc_type BOXED.
Effect
The statement DATA declares a variable of any data type. The declared data object is visible within the current context from this position. Within the declaration part of a class or an interface, DATA declares an instance attribute whose validity is bound to an instance of a class.
This statement has various syntax forms, which allow elementary data types, reference types, structured types, and table types to be defined. With the exception of two additions (VALUE and READ-ONLY), these are the same syntax forms as in the statement TYPES. In this way, a new data type can be defined when declaring a data object. The most important difference compared with the statement TYPES is that a data type defined using DATA (and not derived from an existing type) is available only as a property of the declared data object and is not a standalone data type. This kind of data type is bound to its data object.
For the definition of a structure struc, any data declarations specified are enclosed in two DATA statements with the additions BEGIN OF and END OF. Here a struc structure is declared that contains the enclosed data objects comp as a struc-comp component. Structure definitions can be nested.
For the names var, ref, struc, comp, itab, and rtab, the naming conventions apply.
Notes
◈ The syntax of the statement DATA corresponds to the syntax of the statement TYPES, with the exception of two additions. In this way, a new data type can be defined when declaring a data object. The most important difference compared with the statement TYPES is that a data type defined using DATA (and not derived from an existing type) is available only as a property of the declared data object and is not a standalone data type. This kind of data type is bound to its data object.
◈ Data objects that are declared in a program, but cannot be accessed there statically, produce a warning message in the extended program check.
◈ An inline declaration of variables can be made using the declaration operator DATA.
◈ The obsolete variant DATA ... COMMON PART declares interface work areas.
1. DATA - TYPE abap_type
Syntax
DATA { {var[(len)] TYPE abap_type [DECIMALS dec]}
| {var [TYPE abap_type [LENGTH len] [DECIMALS dec]]} }
[VALUE val|{IS INITIAL}]
[READ-ONLY].
Effect
By specifying a predefined data type abap_type, an elementary variable var is defined. For abap_type, all predefined data types can be used except the internal types b and s.
Syntax and meaning of LENGTH, len, DECIMALS and dec are identical to the definition of elementary data types with TYPES and must be specified within the defined areas. Here, however they are used to create a bound data type. If len or dec are not specified for the ABAP types c, n, p, and x, the bound type is created using the type-friendly standard length and, for p, without decimal places.
Note
For reasons of legibility, it is best to include all information and always use the addition LENGTH, and not parentheses, to specify the length len.
Example
These statements declare three variables and determine their start values.
DATA: text_buffer TYPE string VALUE `Text`,
count TYPE i VALUE 1,
price TYPE p LENGTH 8 DECIMALS 2 VALUE '1.99'.
2. DATA - TYPE, LIKE
Syntax
DATA var { {TYPE [LINE OF] type}
| {LIKE [LINE OF] dobj} }
[VALUE val|{IS INITIAL}]
[READ-ONLY].
Effect
When a type data type or a dobj data object is specified, the data type of variable var is already fully defined before the declaration. The syntax and meaning of the additions TYPE and LIKE are exactly the same as the definition of the data types with TYPES, except that:
◈ For DATA, a standard table type with generic primary table key can be specified after TYPE. This creates a bound table type with a standard key.
◈ For DATA, a table type can be specified after TYPE that is generic with respect to its secondary table key (thanks to the addition WITH FURTHER SECONDARY KEYS). This type attribute is not relevant for the declared data object.
If neither TYPE nor LIKE is specified, a data object with the bound data type c of length 1 is created.
Note
For internal tables, the declaration of the primary table key as a standard key can be critical for various reasons. It is best to define the key fields explicitly instead. In the statement above, therefore, check whether a table with standard key is created by mistake if using a generic standard table type.
Example
These statements define two data objects, both of which have the same data type as the database table spfli.
DATA: spfli_wa1 TYPE spfli,
spfli_wa2 LIKE spfli_wa1.
3. DATA - REF TO
Syntax
DATA ref { {TYPE REF TO type}
| {LIKE REF TO dobj} }
[VALUE IS INITIAL]
[READ-ONLY].
Effect
The addition REF TO declares a reference variable ref. The entry behind REF TO specifies the static type of the reference variable. The static type limits the set of objects to which ref can point. The dynamic type of a reference variable is the data type or the class to which it currently points. The static type is always more general or the same as the dynamic type (see also conversion rule for reference variables).
The syntax and meaning of the additions TYPE and LIKE are the same as the definition of reference types in the section TYPES - REF TO, but here they are used to create a bound reference type.
Only IS INITIAL can be specified as a start value after the addition VALUE.
Note
Reference variables are opaque, which means their content cannot be accessed directly. A reference consists of the address of an object and other administration information.
Example
In this example, an object reference oref and two data references dref1 and dref2 are declared. Both data references are typed fully and can be dereferenced using the dereferencing operator ->* in operand positions.
CLASS c1 DEFINITION.
PUBLIC SECTION.
DATA a1 TYPE i VALUE 1.
ENDCLASS.
DATA: oref TYPE REF TO c1,
dref1 LIKE REF TO oref,
dref2 TYPE REF TO i.
CREATE OBJECT oref.
dref1 = REF #( oref ).
CREATE DATA dref2.
dref2->* = dref1->*->a1.
4. DATA - BEGIN OF struc
Syntax
DATA BEGIN OF struc [READ-ONLY].
...
INCLUDE TYPE|STRUCTURE ...
...
DATA END OF struc.
Effect
Declares a new structure struc. This starts with a DATA statement with the addition BEGIN OF and must end with a DATA statement with the addition END OF.
The following can be included between these DATA statements:
◈ Any DATA statements, in particular further closed structures.
◈ the statements INCLUDE TYPE and INCLUDE STRUCTURE
The meaning of these statements is the same as in the definition of structured data types in the section TYPES - BEGIN OF, but here it is used to generate a bound structured data type. No structure can be created without at least one component.
A component of type struc cannot be declared by referencing struc itself. If the name struc is specified after LIKE in the declaration of a component, a search is performed for the next object with this name in a higher visibility section, and used if found. If a more global object with this name does not exist, a syntax error occurs.
Notes
◈ The addition READ-ONLY can only be used for whole structures and not for individual structure components comp.
◈ A structure called text cannot have any components with three-character names, since these are reserved for addressing text symbols. It is best never to call a structure text and avoid any conflicts with text symbols.
◈ The BOXED addition cannot be specified between DATA BEGIN OF and DATA END OF when declaring components. Static boxes in structures can only be defined with TYPES.
◈ The value operator VALUE can be used to construct the content of structures.
◈ In an obsolete variant, text field literals or the constant space can be specified between BEGIN OF and END OF as anonymous components.
◈ The use of the addition OCCURS for defining standard tables with structured row types is obsolete.
Example
In this example, a structure spfli_struc is declared with an elementary component index and a substructure spfli_wa. The SELECT loop shows a possible use of the nested structure.
DATA: BEGIN OF spfli_struc,
index TYPE i,
spfli_wa TYPE spfli,
END OF spfli_struc.
SELECT *
FROM spfli
INTO @spfli_struc-spfli_wa.
spfli_struc-index = spfli_struc-index + 1.
cl_demo_output=>next_section( |{ spfli_struc-index }| ).
cl_demo_output=>write_data( spfli_struc-spfli_wa ).
ENDSELECT.
cl_demo_output=>display( ).
5. DATA - TABLE OF
Syntax
DATA itab { {TYPE [STANDARD]|SORTED|HASHED TABLE OF [REF TO] type}
| {LIKE [STANDARD]|SORTED|HASHED TABLE OF dobj} }
[tabkeys]
[INITIAL SIZE n]
[VALUE IS INITIAL]
[READ-ONLY].
Effect
This statement defines an internal table. The definition of the row type, table category STANDARD TABLE, SORTED TABLE, or HASHED TABLE and the initial memory size INITIAL SIZE corresponds exactly to the definition of table categories in the section TYPES - TABLE OF. Using DATA, these additions create a bound table type. The generic types ANY TABLE and INDEX TABLE cannot be used with DATA.
tabkeys is used to define the table keys of the internal table, which, unlike data types, cannot be generic.
Notes
◈ When an internal table is created as a data object, only the administration entry for an internal table is created. The actual table rows are not inserted until runtime.
◈ When an internal table is defined, the start value after the VALUE addition must be IS INITIAL.
◈ Several obsolete variants for declaring standard tables exist, described under Obsolete Declarations. In particular, note the obsolete use of the additions WITH HEADER LINE and OCCURS.
Example
Declares an internal hashed table. The row type corresponds to the structure of the database table SPFLI. Two key fields are defined for the primary table key. The other statements demonstrate how the table is filled with rows from database table SPFLI and how a row is read.
DATA: spfli_tab TYPE HASHED TABLE OF spfli
WITH UNIQUE KEY carrid connid,
spfli_wa LIKE LINE OF spfli_tab.
SELECT *
FROM spfli
WHERE carrid = 'LH'
INTO TABLE @spfli_tab.
spfli_wa = spfli_tab[ KEY primary_key
carrid = 'LH' connid = '0400' ].
...
5.1 DATA - tabkeys
Syntax
... [ WITH key ]
[ WITH secondary_key1 ] [ WITH secondary_key2 ] ...
Effect
Defines the table keys in an internal table. The following can be defined:
◈ A primary table key using key.
Every internal table has a primary key. The primary key must be defined explicitly for sorted tables and hashed tables. The information specified for the primary key can only be omitted for standard tables. The primary table key is then automatically defined as a non-unique standard key.
◈ Multiple secondary table keys with secondary_key1, secondary_key2, ....
Secondary keys are an optional specification for all table categories. If no secondary key is specified, the internal table has only one primary key.
- - DATA - key
Syntax
... { [UNIQUE | NON-UNIQUE]
{ {KEY [primary_key [ALIAS key_name] COMPONENTS] comp1 comp2 ...}
| {DEFAULT KEY} } }
| { EMPTY KEY } ...
Alternatives:
1. ... [UNIQUE|NON-UNIQUE] {KEY ...}|{DEFAULT KEY}
2. ... EMPTY KEY
Alternative 1
... [UNIQUE|NON-UNIQUE] {KEY ...}|{DEFAULT KEY}
Effect
Defines the primary table key of an internal table by specifying components or as a standard key. The syntax and semantics of the additions are the same as for the statement TYPES for standalone table types, with the difference that the primary key of a bound table type must always be specified completely:
For standard tables only the addition NON-UNIQUE KEY can be specified. If uniqueness is not specified, this is added implicitly. The addition UNIQUE KEY cannot be specified.
For sorted tables, one of the two additions UNIQUE KEY or NON-UNIQUE KEY must be specified.
For hashed tables, the addition UNIQUE KEY must be specified.
If no primary key is specified for DATA using WITH, the addition WITH NON-UNIQUE DEFAULT KEY is added implicitly for standard tables. This gives the table a standard key, which can be empty. In sorted tables and hashed tables, the primary key must be specified explicitly and cannot be empty.
If the name of the primary key primary_key is specified explicitly, the addition WITH HEADER LINE can no longer be specified, even outside the classes.
Note
The declaration of the primary table key as a standard key can be critical for various reasons. It is best to specify key fields explicitly instead. In particular, make sure that the declaration of the standard key is not added by mistake because the key has not been specified explicitly.
Alternative 2
... EMPTY KEY
Effect
Defines an empty primary key in an internal table. This variant is possible for standard tables only. The syntax and semantics are the same as for the statement TYPES.
Notes
◈ The addition EMPTY KEY can clarify situations where the definition of a table key is not important.
◈ In general, EMPTY KEY is recommended instead of not specifying a key definition, since otherwise the standard key is used, which can often produce unexpected results.
- - DATA - secondary_key
Syntax
... {UNIQUE HASHED}|{UNIQUE SORTED}|{NON-UNIQUE SORTED}
KEY key_name COMPONENTS comp1 comp2 ...
Effect
Defines a secondary table key of an internal table. The syntax and semantics of the additions are the same as those for the statement TYPES for standalone table types.
Notes
◈ When internal tables are accessed using the statements READ TABLE itab, LOOP AT itab, MODIFY itab and DELETE itab or using table expressions and in mesh types and mesh paths, a secondary key can be used to specify the rows to be processed or the processing order. To do this, the additions WITH [TABLE] KEY ... COMPONENTS or USING KEY must be specified in the statements and KEY in table expressions.A secondary key is never used implicitly.
◈ The statement INSERT itab determines the insert position using the primary key and primary index only. A secondary key can be specified only for the source table from which multiple rows are copied. The latter also applies to the statement APPEND.
◈ If different table keys for an internal table contain the same components, the syntax check issues a warning (which can be hidden using a pragma). In the case of references to a non-generic table type defined using TYPES, a specified pragma is also applied to the DATA statement. In the case of references to a generic table type for which no primary table key is defined, the specified pragma is not applied to the DATA statement, since this statement uses a complete table type implicitly and the pragma must also be specified in the case of DATA.
◈ If a secondary key is defined, the addition WITH HEADER LINE can no longer be specified, even outside classes.
Example
The DEMO_SECONDARY_KEYS program demonstrates the declaration and use of a secondary table key and the resulting performance gains.
6. DATA - RANGE OF
Syntax
DATA rtab {TYPE RANGE OF type}|{LIKE RANGE OFdobj}
[INITIAL SIZE n]
[VALUE IS INITIAL]
[READ-ONLY].
Effect
This statement defines a ranges table rtab with the table type described in the section TYPES - RANGE OF. The table type defined here, however, is not a standalone type, but exists as a property of the data object rtab.
The addition VALUE IS INITIAL can be used to specify an initial start value.
Notes
◈ Outside of classes, the addition WITH HEADER LINE can also be used to declare an obsolete header line.
◈ Declarations of ranges tables using the statement RANGES are obsolete.
Example
In this example, a ranges table is declared, filled, and evaluated in the WHERE condition of a SELECT statement.
DATA: spfli_wa TYPE spfli,
r_carrid TYPE RANGE OF spfli-carrid,
r_carrid_line LIKE LINE OF r_carrid.
r_carrid_line-sign = 'I'.
r_carrid_line-option = 'BT'.
r_carrid_line-low = 'AA'.
r_carrid_line-high = 'LH'.
APPEND r_carrid_line TO r_carrid.
SELECT *
FROM spfli
WHERE carrid IN @r_carrid
INTO @spfli_wa.
...
ENDSELECT.
7. DATA - LOB HANDLE
Syntax
DATA dtype TYPE dbtab|view [READ-ONLY]
lob_handle_type FOR lob_handle_columns
[ lob_handle_type FOR lob_handle_columns
... ].
Effect
Derives an LOB handle structure as a work area for working with streaming and locators in Open SQL. dbtab expects a database table defined in ABAP Dictionary or a database view defined for view in ABAP Dictionary.
The specified columns lob_handle_columns are used to determine LOBs from dbtab or view for which LOB handle components are created in the structure. Their static type is determined using the specified type lob_handle_type.
The syntax and meaning of the additions are exactly the same as the definition of LOB handle structures using the corresponding variant of the statement TYPES +.
8. DATA - BOXED
Syntax
DATA struc TYPE struc_type BOXED.
Effect
This statement defines a structured attribute of a class or an interface as a static box. It can only be located in the declaration part of a class or an interface and only at the highest level.
struc_type expects a structured data type. This can be a program-local structure, a visible structured type of a class or of a global interface, or a structure from ABAP Dictionary, and can contain boxed components.
Static boxes support initial value sharing. Here, the structure is not saved in the higher level context itself. Instead, an internal reference that points to the actual structure is saved in place of the component. This makes a static box a deep component.
Notes
◈ A structure with a static box is a deep structure and the relevant restrictions apply.
◈ The addition BOXED defines the static box with reference to its context (structure or class). A data type declared using a direct TYPE reference or LIKE reference to a static box is assigned its data type but is not a static box itself.
◈ When a static box is transferred from one structure to another structure using the statement INCLUDE TYPE|STRUCTURE, its static attribute is also transferred.
◈ The addition BOXED can also be used in the statement TYPES to declare a substructure of a nested structured data type.
Example
The following section shows the allowed usage of the addition BOXED with the statement [CLASS-]DATA. In a class, it declares a static structure struc1 and a structured instance attribute struc2 as a static box.
CLASS c1 DEFINITION.
PUBLIC SECTION.
TYPES: BEGIN OF t_struc,
comp1 TYPE c LENGTH 100,
comp2 TYPE n LENGTH 100,
END OF t_struc.
PRIVATE SECTION.
CLASS-DATA struc1 TYPE t_struc BOXED.
DATA struc2 TYPE t100 BOXED.
ENDCLASS.
9. DATA - data_options
Syntax
... [ VALUE val|{IS INITIAL} ]
[ READ-ONLY ].
Additions
1. ... VALUE val|{IS INITIAL}
2. ... READ-ONLY
Effect
The additions VALUE and READ-ONLY are specifically for data objects. They distinguish the DATA syntax from the TYPES syntax.
Note
As well as the additions VALUE and READ-ONLY, the syntax also allows the obsolete addition COMMON PART.
Addition 1
... VALUE val|{IS INITIAL}
Effect
The addition VALUE can be used to define (for all forms of the variable declaration) a start value val for the content of the variable. This is used to initialize the variable when created before LOAD-OF-PROGRAM. The addition VALUE is not allowed in the declaration part of an interface in the statement DATA.
The start value val can either be specified as a literal or as a predefined constant. Where constants are involved, they work like the literal specified after VALUE when the constant is declared, rather than their actual values being used. A check is usually performed to verify if the length of the specified value matches the data type. Any deviations produce a warning from the syntax check. If the data type of the literal does not match the data type of the declaration, it is usually converted in accordance with the conversion rules for elementary data types.
Without the addition VALUE, or if IS INITIAL is specified, the content is set to an initial value. The initial values are dependent on the data type.
In the case of initial structures, the components are initial; initial reference variables contain the null reference that does not point to an object, and initial internal tables do not contain any rows.
The addition VALUE is possible for all data types, in particular for the deep types (strings, reference types, table types, or structured types with deep components, including boxed components). A start value val, however, can only be specified for the ABAP types string and xstring. Otherwise, only IS INITIAL is possible. IS INITIAL is also the only possible start value for structures with components that are not just character-like and flat.
Notes
◈ A start value should be specified as type-friendly as possible. In particular, no longer values should be specified and, in the case of certain data types such as d and t, the length must match exactly.
◈ If numbers with decimal places are specified or if, in the scientific notation with mantissa, an exponent is used as a start value for data objects of the data types p or f, there are no literals for these numbers. Instead, the character literals must be specified with the appropriate content. These are then converted into the numeric data type in accordance with the conversion rules for elementary data types. The same applies to byte-like data objects.
◈ The value operator VALUE can also be used to construct the content of complex data objects (structures, internal tables).
Addition 2
... READ-ONLY
Effect
This addition is always possible in the public visibility section of a class or in an interface. This addition makes an attribute declared using DATA readable from outside of the class, but can only be changed using methods of the class or its subclasses. This addition is ignored by the friends of the class.
A class attribute defined using READ-ONLY can be used outside of the class, its friends, and subclasses only in reading positions in ABAP statements.
Notes
◈ The declaration of attributes using the addition READ-ONLY does not prevent methods of the class from passing references to these attributes externally as reference variables or field symbols and therefore making the attributes modifiable outside of the class.
◈ The addition READ-ONLY is always recommended if attributes need to be invisible, but a GET method for every read is to be avoided.
Syntax Forms
Using Predefined Types
1. DATA { {var[(len)] TYPE abap_type [DECIMALS dec]}
| {var TYPE abap_type [LENGTH len] [DECIMALS dec]} }
[VALUE val|{IS INITIAL}]
[READ-ONLY].
Reference to Existing Types
2. DATA var { {TYPE [LINE OF] type}
| {LIKE [LINE OF] dobj} }
[VALUE val|{IS INITIAL}]
[READ-ONLY].
Reference Variables
3. DATA ref { {TYPE REF TO type}
| {LIKE REF TO dobj} }
[VALUE IS INITIAL]
[READ-ONLY].
Structures
4. DATA BEGIN OF struc [READ-ONLY].
...
DATA comp ...
INCLUDE {TYPE|STRUCTURE} ...
...
DATA END OF struc.
Internal Tables
5. DATA itab { {TYPE tabkind OF [REF TO] type}
| {LIKE tabkind OF dobj} }
[ tabkeys] [INITIAL SIZE n]
[WITH HEADER LINE]
[VALUE IS INITIAL]
[READ-ONLY].
Ranges Table
6. DATA rtab {TYPE RANGE OF type}|{LIKE RANGE OF dobj}
[INITIAL SIZE n]
[WITH HEADER LINE]
[VALUE IS INITIAL]
[READ-ONLY].
LOB Handle Structures
7. DATA dtype TYPE dbtab|view [READ-ONLY]
lob_handle_type FOR lob_handle_columns
[ lob_handle_type FOR lob_handle_columns
... ].
Static Boxed Components
8. DATA struc TYPE struc_type BOXED.
Effect
The statement DATA declares a variable of any data type. The declared data object is visible within the current context from this position. Within the declaration part of a class or an interface, DATA declares an instance attribute whose validity is bound to an instance of a class.
This statement has various syntax forms, which allow elementary data types, reference types, structured types, and table types to be defined. With the exception of two additions (VALUE and READ-ONLY), these are the same syntax forms as in the statement TYPES. In this way, a new data type can be defined when declaring a data object. The most important difference compared with the statement TYPES is that a data type defined using DATA (and not derived from an existing type) is available only as a property of the declared data object and is not a standalone data type. This kind of data type is bound to its data object.
For the definition of a structure struc, any data declarations specified are enclosed in two DATA statements with the additions BEGIN OF and END OF. Here a struc structure is declared that contains the enclosed data objects comp as a struc-comp component. Structure definitions can be nested.
For the names var, ref, struc, comp, itab, and rtab, the naming conventions apply.
Notes
◈ The syntax of the statement DATA corresponds to the syntax of the statement TYPES, with the exception of two additions. In this way, a new data type can be defined when declaring a data object. The most important difference compared with the statement TYPES is that a data type defined using DATA (and not derived from an existing type) is available only as a property of the declared data object and is not a standalone data type. This kind of data type is bound to its data object.
◈ Data objects that are declared in a program, but cannot be accessed there statically, produce a warning message in the extended program check.
◈ An inline declaration of variables can be made using the declaration operator DATA.
◈ The obsolete variant DATA ... COMMON PART declares interface work areas.
1. DATA - TYPE abap_type
Syntax
DATA { {var[(len)] TYPE abap_type [DECIMALS dec]}
| {var [TYPE abap_type [LENGTH len] [DECIMALS dec]]} }
[VALUE val|{IS INITIAL}]
[READ-ONLY].
Effect
By specifying a predefined data type abap_type, an elementary variable var is defined. For abap_type, all predefined data types can be used except the internal types b and s.
Syntax and meaning of LENGTH, len, DECIMALS and dec are identical to the definition of elementary data types with TYPES and must be specified within the defined areas. Here, however they are used to create a bound data type. If len or dec are not specified for the ABAP types c, n, p, and x, the bound type is created using the type-friendly standard length and, for p, without decimal places.
Note
For reasons of legibility, it is best to include all information and always use the addition LENGTH, and not parentheses, to specify the length len.
Example
These statements declare three variables and determine their start values.
DATA: text_buffer TYPE string VALUE `Text`,
count TYPE i VALUE 1,
price TYPE p LENGTH 8 DECIMALS 2 VALUE '1.99'.
2. DATA - TYPE, LIKE
Syntax
DATA var { {TYPE [LINE OF] type}
| {LIKE [LINE OF] dobj} }
[VALUE val|{IS INITIAL}]
[READ-ONLY].
Effect
When a type data type or a dobj data object is specified, the data type of variable var is already fully defined before the declaration. The syntax and meaning of the additions TYPE and LIKE are exactly the same as the definition of the data types with TYPES, except that:
◈ For DATA, a standard table type with generic primary table key can be specified after TYPE. This creates a bound table type with a standard key.
◈ For DATA, a table type can be specified after TYPE that is generic with respect to its secondary table key (thanks to the addition WITH FURTHER SECONDARY KEYS). This type attribute is not relevant for the declared data object.
If neither TYPE nor LIKE is specified, a data object with the bound data type c of length 1 is created.
Note
For internal tables, the declaration of the primary table key as a standard key can be critical for various reasons. It is best to define the key fields explicitly instead. In the statement above, therefore, check whether a table with standard key is created by mistake if using a generic standard table type.
Example
These statements define two data objects, both of which have the same data type as the database table spfli.
DATA: spfli_wa1 TYPE spfli,
spfli_wa2 LIKE spfli_wa1.
3. DATA - REF TO
Syntax
DATA ref { {TYPE REF TO type}
| {LIKE REF TO dobj} }
[VALUE IS INITIAL]
[READ-ONLY].
Effect
The addition REF TO declares a reference variable ref. The entry behind REF TO specifies the static type of the reference variable. The static type limits the set of objects to which ref can point. The dynamic type of a reference variable is the data type or the class to which it currently points. The static type is always more general or the same as the dynamic type (see also conversion rule for reference variables).
The syntax and meaning of the additions TYPE and LIKE are the same as the definition of reference types in the section TYPES - REF TO, but here they are used to create a bound reference type.
Only IS INITIAL can be specified as a start value after the addition VALUE.
Note
Reference variables are opaque, which means their content cannot be accessed directly. A reference consists of the address of an object and other administration information.
Example
In this example, an object reference oref and two data references dref1 and dref2 are declared. Both data references are typed fully and can be dereferenced using the dereferencing operator ->* in operand positions.
CLASS c1 DEFINITION.
PUBLIC SECTION.
DATA a1 TYPE i VALUE 1.
ENDCLASS.
DATA: oref TYPE REF TO c1,
dref1 LIKE REF TO oref,
dref2 TYPE REF TO i.
CREATE OBJECT oref.
dref1 = REF #( oref ).
CREATE DATA dref2.
dref2->* = dref1->*->a1.
Syntax
DATA BEGIN OF struc [READ-ONLY].
...
INCLUDE TYPE|STRUCTURE ...
...
DATA END OF struc.
Effect
Declares a new structure struc. This starts with a DATA statement with the addition BEGIN OF and must end with a DATA statement with the addition END OF.
The following can be included between these DATA statements:
◈ Any DATA statements, in particular further closed structures.
◈ the statements INCLUDE TYPE and INCLUDE STRUCTURE
The meaning of these statements is the same as in the definition of structured data types in the section TYPES - BEGIN OF, but here it is used to generate a bound structured data type. No structure can be created without at least one component.
A component of type struc cannot be declared by referencing struc itself. If the name struc is specified after LIKE in the declaration of a component, a search is performed for the next object with this name in a higher visibility section, and used if found. If a more global object with this name does not exist, a syntax error occurs.
Notes
◈ The addition READ-ONLY can only be used for whole structures and not for individual structure components comp.
◈ A structure called text cannot have any components with three-character names, since these are reserved for addressing text symbols. It is best never to call a structure text and avoid any conflicts with text symbols.
◈ The BOXED addition cannot be specified between DATA BEGIN OF and DATA END OF when declaring components. Static boxes in structures can only be defined with TYPES.
◈ The value operator VALUE can be used to construct the content of structures.
◈ In an obsolete variant, text field literals or the constant space can be specified between BEGIN OF and END OF as anonymous components.
◈ The use of the addition OCCURS for defining standard tables with structured row types is obsolete.
Example
In this example, a structure spfli_struc is declared with an elementary component index and a substructure spfli_wa. The SELECT loop shows a possible use of the nested structure.
DATA: BEGIN OF spfli_struc,
index TYPE i,
spfli_wa TYPE spfli,
END OF spfli_struc.
SELECT *
FROM spfli
INTO @spfli_struc-spfli_wa.
spfli_struc-index = spfli_struc-index + 1.
cl_demo_output=>next_section( |{ spfli_struc-index }| ).
cl_demo_output=>write_data( spfli_struc-spfli_wa ).
ENDSELECT.
cl_demo_output=>display( ).
5. DATA - TABLE OF
Syntax
DATA itab { {TYPE [STANDARD]|SORTED|HASHED TABLE OF [REF TO] type}
| {LIKE [STANDARD]|SORTED|HASHED TABLE OF dobj} }
[tabkeys]
[INITIAL SIZE n]
[VALUE IS INITIAL]
[READ-ONLY].
Effect
This statement defines an internal table. The definition of the row type, table category STANDARD TABLE, SORTED TABLE, or HASHED TABLE and the initial memory size INITIAL SIZE corresponds exactly to the definition of table categories in the section TYPES - TABLE OF. Using DATA, these additions create a bound table type. The generic types ANY TABLE and INDEX TABLE cannot be used with DATA.
tabkeys is used to define the table keys of the internal table, which, unlike data types, cannot be generic.
Notes
◈ When an internal table is created as a data object, only the administration entry for an internal table is created. The actual table rows are not inserted until runtime.
◈ When an internal table is defined, the start value after the VALUE addition must be IS INITIAL.
◈ Several obsolete variants for declaring standard tables exist, described under Obsolete Declarations. In particular, note the obsolete use of the additions WITH HEADER LINE and OCCURS.
Example
Declares an internal hashed table. The row type corresponds to the structure of the database table SPFLI. Two key fields are defined for the primary table key. The other statements demonstrate how the table is filled with rows from database table SPFLI and how a row is read.
DATA: spfli_tab TYPE HASHED TABLE OF spfli
WITH UNIQUE KEY carrid connid,
spfli_wa LIKE LINE OF spfli_tab.
SELECT *
FROM spfli
WHERE carrid = 'LH'
INTO TABLE @spfli_tab.
spfli_wa = spfli_tab[ KEY primary_key
carrid = 'LH' connid = '0400' ].
...
5.1 DATA - tabkeys
Syntax
... [ WITH key ]
[ WITH secondary_key1 ] [ WITH secondary_key2 ] ...
Effect
Defines the table keys in an internal table. The following can be defined:
◈ A primary table key using key.
Every internal table has a primary key. The primary key must be defined explicitly for sorted tables and hashed tables. The information specified for the primary key can only be omitted for standard tables. The primary table key is then automatically defined as a non-unique standard key.
◈ Multiple secondary table keys with secondary_key1, secondary_key2, ....
Secondary keys are an optional specification for all table categories. If no secondary key is specified, the internal table has only one primary key.
- - DATA - key
Syntax
... { [UNIQUE | NON-UNIQUE]
{ {KEY [primary_key [ALIAS key_name] COMPONENTS] comp1 comp2 ...}
| {DEFAULT KEY} } }
| { EMPTY KEY } ...
Alternatives:
1. ... [UNIQUE|NON-UNIQUE] {KEY ...}|{DEFAULT KEY}
2. ... EMPTY KEY
Alternative 1
... [UNIQUE|NON-UNIQUE] {KEY ...}|{DEFAULT KEY}
Effect
Defines the primary table key of an internal table by specifying components or as a standard key. The syntax and semantics of the additions are the same as for the statement TYPES for standalone table types, with the difference that the primary key of a bound table type must always be specified completely:
For standard tables only the addition NON-UNIQUE KEY can be specified. If uniqueness is not specified, this is added implicitly. The addition UNIQUE KEY cannot be specified.
For sorted tables, one of the two additions UNIQUE KEY or NON-UNIQUE KEY must be specified.
For hashed tables, the addition UNIQUE KEY must be specified.
If no primary key is specified for DATA using WITH, the addition WITH NON-UNIQUE DEFAULT KEY is added implicitly for standard tables. This gives the table a standard key, which can be empty. In sorted tables and hashed tables, the primary key must be specified explicitly and cannot be empty.
If the name of the primary key primary_key is specified explicitly, the addition WITH HEADER LINE can no longer be specified, even outside the classes.
Note
The declaration of the primary table key as a standard key can be critical for various reasons. It is best to specify key fields explicitly instead. In particular, make sure that the declaration of the standard key is not added by mistake because the key has not been specified explicitly.
Alternative 2
... EMPTY KEY
Effect
Defines an empty primary key in an internal table. This variant is possible for standard tables only. The syntax and semantics are the same as for the statement TYPES.
Notes
◈ The addition EMPTY KEY can clarify situations where the definition of a table key is not important.
◈ In general, EMPTY KEY is recommended instead of not specifying a key definition, since otherwise the standard key is used, which can often produce unexpected results.
- - DATA - secondary_key
Syntax
... {UNIQUE HASHED}|{UNIQUE SORTED}|{NON-UNIQUE SORTED}
KEY key_name COMPONENTS comp1 comp2 ...
Effect
Defines a secondary table key of an internal table. The syntax and semantics of the additions are the same as those for the statement TYPES for standalone table types.
Notes
◈ When internal tables are accessed using the statements READ TABLE itab, LOOP AT itab, MODIFY itab and DELETE itab or using table expressions and in mesh types and mesh paths, a secondary key can be used to specify the rows to be processed or the processing order. To do this, the additions WITH [TABLE] KEY ... COMPONENTS or USING KEY must be specified in the statements and KEY in table expressions.A secondary key is never used implicitly.
◈ The statement INSERT itab determines the insert position using the primary key and primary index only. A secondary key can be specified only for the source table from which multiple rows are copied. The latter also applies to the statement APPEND.
◈ If different table keys for an internal table contain the same components, the syntax check issues a warning (which can be hidden using a pragma). In the case of references to a non-generic table type defined using TYPES, a specified pragma is also applied to the DATA statement. In the case of references to a generic table type for which no primary table key is defined, the specified pragma is not applied to the DATA statement, since this statement uses a complete table type implicitly and the pragma must also be specified in the case of DATA.
◈ If a secondary key is defined, the addition WITH HEADER LINE can no longer be specified, even outside classes.
Example
The DEMO_SECONDARY_KEYS program demonstrates the declaration and use of a secondary table key and the resulting performance gains.
6. DATA - RANGE OF
Syntax
DATA rtab {TYPE RANGE OF type}|{LIKE RANGE OFdobj}
[INITIAL SIZE n]
[VALUE IS INITIAL]
[READ-ONLY].
Effect
This statement defines a ranges table rtab with the table type described in the section TYPES - RANGE OF. The table type defined here, however, is not a standalone type, but exists as a property of the data object rtab.
The addition VALUE IS INITIAL can be used to specify an initial start value.
Notes
◈ Outside of classes, the addition WITH HEADER LINE can also be used to declare an obsolete header line.
◈ Declarations of ranges tables using the statement RANGES are obsolete.
Example
In this example, a ranges table is declared, filled, and evaluated in the WHERE condition of a SELECT statement.
DATA: spfli_wa TYPE spfli,
r_carrid TYPE RANGE OF spfli-carrid,
r_carrid_line LIKE LINE OF r_carrid.
r_carrid_line-sign = 'I'.
r_carrid_line-option = 'BT'.
r_carrid_line-low = 'AA'.
r_carrid_line-high = 'LH'.
APPEND r_carrid_line TO r_carrid.
SELECT *
FROM spfli
WHERE carrid IN @r_carrid
INTO @spfli_wa.
...
ENDSELECT.
Syntax
DATA dtype TYPE dbtab|view [READ-ONLY]
lob_handle_type FOR lob_handle_columns
[ lob_handle_type FOR lob_handle_columns
... ].
Effect
Derives an LOB handle structure as a work area for working with streaming and locators in Open SQL. dbtab expects a database table defined in ABAP Dictionary or a database view defined for view in ABAP Dictionary.
The specified columns lob_handle_columns are used to determine LOBs from dbtab or view for which LOB handle components are created in the structure. Their static type is determined using the specified type lob_handle_type.
The syntax and meaning of the additions are exactly the same as the definition of LOB handle structures using the corresponding variant of the statement TYPES +.
8. DATA - BOXED
Syntax
DATA struc TYPE struc_type BOXED.
Effect
This statement defines a structured attribute of a class or an interface as a static box. It can only be located in the declaration part of a class or an interface and only at the highest level.
struc_type expects a structured data type. This can be a program-local structure, a visible structured type of a class or of a global interface, or a structure from ABAP Dictionary, and can contain boxed components.
Static boxes support initial value sharing. Here, the structure is not saved in the higher level context itself. Instead, an internal reference that points to the actual structure is saved in place of the component. This makes a static box a deep component.
Notes
◈ A structure with a static box is a deep structure and the relevant restrictions apply.
◈ The addition BOXED defines the static box with reference to its context (structure or class). A data type declared using a direct TYPE reference or LIKE reference to a static box is assigned its data type but is not a static box itself.
◈ When a static box is transferred from one structure to another structure using the statement INCLUDE TYPE|STRUCTURE, its static attribute is also transferred.
◈ The addition BOXED can also be used in the statement TYPES to declare a substructure of a nested structured data type.
Example
The following section shows the allowed usage of the addition BOXED with the statement [CLASS-]DATA. In a class, it declares a static structure struc1 and a structured instance attribute struc2 as a static box.
CLASS c1 DEFINITION.
PUBLIC SECTION.
TYPES: BEGIN OF t_struc,
comp1 TYPE c LENGTH 100,
comp2 TYPE n LENGTH 100,
END OF t_struc.
PRIVATE SECTION.
CLASS-DATA struc1 TYPE t_struc BOXED.
DATA struc2 TYPE t100 BOXED.
ENDCLASS.
Syntax
... [ VALUE val|{IS INITIAL} ]
[ READ-ONLY ].
Additions
1. ... VALUE val|{IS INITIAL}
2. ... READ-ONLY
Effect
The additions VALUE and READ-ONLY are specifically for data objects. They distinguish the DATA syntax from the TYPES syntax.
Note
As well as the additions VALUE and READ-ONLY, the syntax also allows the obsolete addition COMMON PART.
Addition 1
... VALUE val|{IS INITIAL}
Effect
The addition VALUE can be used to define (for all forms of the variable declaration) a start value val for the content of the variable. This is used to initialize the variable when created before LOAD-OF-PROGRAM. The addition VALUE is not allowed in the declaration part of an interface in the statement DATA.
The start value val can either be specified as a literal or as a predefined constant. Where constants are involved, they work like the literal specified after VALUE when the constant is declared, rather than their actual values being used. A check is usually performed to verify if the length of the specified value matches the data type. Any deviations produce a warning from the syntax check. If the data type of the literal does not match the data type of the declaration, it is usually converted in accordance with the conversion rules for elementary data types.
Without the addition VALUE, or if IS INITIAL is specified, the content is set to an initial value. The initial values are dependent on the data type.
In the case of initial structures, the components are initial; initial reference variables contain the null reference that does not point to an object, and initial internal tables do not contain any rows.
The addition VALUE is possible for all data types, in particular for the deep types (strings, reference types, table types, or structured types with deep components, including boxed components). A start value val, however, can only be specified for the ABAP types string and xstring. Otherwise, only IS INITIAL is possible. IS INITIAL is also the only possible start value for structures with components that are not just character-like and flat.
Notes
◈ A start value should be specified as type-friendly as possible. In particular, no longer values should be specified and, in the case of certain data types such as d and t, the length must match exactly.
◈ If numbers with decimal places are specified or if, in the scientific notation with mantissa, an exponent is used as a start value for data objects of the data types p or f, there are no literals for these numbers. Instead, the character literals must be specified with the appropriate content. These are then converted into the numeric data type in accordance with the conversion rules for elementary data types. The same applies to byte-like data objects.
◈ The value operator VALUE can also be used to construct the content of complex data objects (structures, internal tables).
Addition 2
... READ-ONLY
Effect
This addition is always possible in the public visibility section of a class or in an interface. This addition makes an attribute declared using DATA readable from outside of the class, but can only be changed using methods of the class or its subclasses. This addition is ignored by the friends of the class.
A class attribute defined using READ-ONLY can be used outside of the class, its friends, and subclasses only in reading positions in ABAP statements.
Notes
◈ The declaration of attributes using the addition READ-ONLY does not prevent methods of the class from passing references to these attributes externally as reference variables or field symbols and therefore making the attributes modifiable outside of the class.
◈ The addition READ-ONLY is always recommended if attributes need to be invisible, but a GET method for every read is to be avoided.
⇰ CONSTANTS
Syntax
CONSTANTS const [options].
Effect
This statement declares a constant data object, const for short. The content of a constant cannot be changed at runtime of an ABAP program. It can only be used as an operand in reading positions of ABAP statements. Constants declared in the declaration part of a class or an interface are static attributes of that class or interface.
The naming conventions apply to the name const. The syntax of the additions options of the statement CONSTANTS statement for declaring constants matches the statement DATA for declaring variables. Only the additions READ-ONLY, BOXED, and the declaration of LOB handle structures are not possible. As previously, the statement INCLUDE cannot be used within the declaration of a structure.
Unlike the DATA statement, an initial value with the addition VALUE must be specified when using the CONSTANTS statement. The same restrictions as for the DATA statement apply. This has the following implications for the declaration of constants with deep data types:
A start value val can be specified for the ABAP types string and xstring only.
Constant internal tables, reference variables, and structures with components that are not just character-like and flat can be assigned their initial value by IS INITIAL only, and are therefore always initial.
Notes
◈ If the class component selector is used, the interface name can also be used to access static attributes of interfaces declared using CONSTANTS.
◈ Constants are stored in the PXA and are available to all programs.
Example
The statements below declare a numeric constant, a constant structure, and a constant reference. The reference can be used in comparisons, for example, or passed to procedures.
CONSTANTS pi TYPE p LENGTH 8 DECIMALS 14
VALUE '3.14159265358979'.
CONSTANTS: BEGIN OF sap_ag,
zip_code TYPE n LENGTH 5 VALUE '69189',
city TYPE string VALUE `Walldorf`,
country TYPE string VALUE `Germany`,
END OF sap_ag.
CONSTANTS null_pointer TYPE REF TO object VALUE IS INITIAL.
Syntax
CONSTANTS const [options].
Effect
This statement declares a constant data object, const for short. The content of a constant cannot be changed at runtime of an ABAP program. It can only be used as an operand in reading positions of ABAP statements. Constants declared in the declaration part of a class or an interface are static attributes of that class or interface.
The naming conventions apply to the name const. The syntax of the additions options of the statement CONSTANTS statement for declaring constants matches the statement DATA for declaring variables. Only the additions READ-ONLY, BOXED, and the declaration of LOB handle structures are not possible. As previously, the statement INCLUDE cannot be used within the declaration of a structure.
Unlike the DATA statement, an initial value with the addition VALUE must be specified when using the CONSTANTS statement. The same restrictions as for the DATA statement apply. This has the following implications for the declaration of constants with deep data types:
A start value val can be specified for the ABAP types string and xstring only.
Constant internal tables, reference variables, and structures with components that are not just character-like and flat can be assigned their initial value by IS INITIAL only, and are therefore always initial.
Notes
◈ If the class component selector is used, the interface name can also be used to access static attributes of interfaces declared using CONSTANTS.
◈ Constants are stored in the PXA and are available to all programs.
Example
The statements below declare a numeric constant, a constant structure, and a constant reference. The reference can be used in comparisons, for example, or passed to procedures.
CONSTANTS pi TYPE p LENGTH 8 DECIMALS 14
VALUE '3.14159265358979'.
CONSTANTS: BEGIN OF sap_ag,
zip_code TYPE n LENGTH 5 VALUE '69189',
city TYPE string VALUE `Walldorf`,
country TYPE string VALUE `Germany`,
END OF sap_ag.
CONSTANTS null_pointer TYPE REF TO object VALUE IS INITIAL.
⇰ STATICS
Syntax
STATICS stat [options].
Effect
Declares static variables stat. The statement STATICS for declaring static variables can only be used in static methods, function modules, and subroutines.
The naming conventions apply to the stat name. The syntax of the additions options is the same as for the statement DATA for declaring normal variables. Only the additions READ-ONLY, BOXED, and the declaration of LOB handle structures are not possible.
As with normal local variables, variables declared with STATICS are only visible within the procedure. The lifespan of a variable declared with STATICS is the same as that of a global data object. The variable is created once when the master program is loaded to the internal session, and its content is assigned the start value of the VALUE addition. Calling and ending the procedure have no effect on the lifespan and content.
Note
In instance methods, the statement STATICS is not allowed. Instead, static attributes of the class declared using CLASS-DATA can be used.
Example
The subroutine add_one returns the same result for the variable local for each call as this is instantiated again each time. The static variable static is already available and its value increased by 1 during each call.
DO 10 TIMES.
PERFORM add_one.
ENDDO.
cl_demo_output=>display( ).
FORM add_one.
DATA local TYPE i VALUE 10.
STATICS static TYPE i VALUE 10.
local = local + 1.
static = static + 1.
cl_demo_output=>write( |Local: { local }, | &&
|Static: { static }| ).
ENDFORM.
Syntax
STATICS stat [options].
Effect
Declares static variables stat. The statement STATICS for declaring static variables can only be used in static methods, function modules, and subroutines.
The naming conventions apply to the stat name. The syntax of the additions options is the same as for the statement DATA for declaring normal variables. Only the additions READ-ONLY, BOXED, and the declaration of LOB handle structures are not possible.
As with normal local variables, variables declared with STATICS are only visible within the procedure. The lifespan of a variable declared with STATICS is the same as that of a global data object. The variable is created once when the master program is loaded to the internal session, and its content is assigned the start value of the VALUE addition. Calling and ending the procedure have no effect on the lifespan and content.
Note
In instance methods, the statement STATICS is not allowed. Instead, static attributes of the class declared using CLASS-DATA can be used.
Example
The subroutine add_one returns the same result for the variable local for each call as this is instantiated again each time. The static variable static is already available and its value increased by 1 during each call.
DO 10 TIMES.
PERFORM add_one.
ENDDO.
cl_demo_output=>display( ).
FORM add_one.
DATA local TYPE i VALUE 10.
STATICS static TYPE i VALUE 10.
local = local + 1.
static = static + 1.
cl_demo_output=>write( |Local: { local }, | &&
|Static: { static }| ).
ENDFORM.
⇰ TABLES
Syntax
TABLES table_wa.
Effect
This statement is not allowed in classes and declares a data object table_wa as a table work area whose data type is taken from the identically named structured data type table_wa in ABAP Dictionary. table_wa must be defined as a flat structure in ABAP Dictionary. This means either database tables or classic views can be specified for table_wa.
Table work areas declared using TABLES are interface work areas and should only be declared in the global declaration part of a program for the following purpose:
◈ The statement TABLES is required for exchanging data between dynpro fields defined in a program dynpro by being taken from ABAP Dictionary, and the ABAP program. For the dynpro event PBO, the content of the table work area is passed to identically named dynpro fields; for PAI, the system takes the data from identically named dynpro fields.
◈ In executable programs, flat table work areas can be used to copy data that is provided for the event GET table_wa from an associated logical database. TABLES is synonymous with the statement NODES for this purpose.
Notes
◈ Table areas declared using NODES behave like common data declared using the addition COMMON PART. They are shared by the programs of a program group. This feature should not be exploited due to the reasons outlined in Program Groups in External Procedure Calls.
◈ Table work areas declared using TABLES can be declared in subroutines and function modules, however this is not recommended. A table work area declared in a procedure is not local but belongs to the context of a master program. The table work area is visible as soon as the master program is declared and exists for the duration of the master program. In contrast to normal program-global data, the content of the table work areas declared in subroutines and function modules is stored temporarily when these subroutines and function modules are called. Assignments that were made during runtime of the procedure are preserved until the procedure is completed. When the procedure is exited, the table work areas are filled with the contents they contained when the procedure was called. Table work areas declared in procedures behave like global data to which the statement LOCAL is applied in the procedure.
◈ Always use NODES and not TABLES for interface work areas for logical databases. This makes it clear that they are nodes of logical databases.
◈ A CDS entity cannot be specified after TABLES. However, a CDS database view of a CDS view can be specified.
◈ The variant TABLES * is completely obsolete.
Syntax
TABLES table_wa.
Effect
This statement is not allowed in classes and declares a data object table_wa as a table work area whose data type is taken from the identically named structured data type table_wa in ABAP Dictionary. table_wa must be defined as a flat structure in ABAP Dictionary. This means either database tables or classic views can be specified for table_wa.
Table work areas declared using TABLES are interface work areas and should only be declared in the global declaration part of a program for the following purpose:
◈ The statement TABLES is required for exchanging data between dynpro fields defined in a program dynpro by being taken from ABAP Dictionary, and the ABAP program. For the dynpro event PBO, the content of the table work area is passed to identically named dynpro fields; for PAI, the system takes the data from identically named dynpro fields.
◈ In executable programs, flat table work areas can be used to copy data that is provided for the event GET table_wa from an associated logical database. TABLES is synonymous with the statement NODES for this purpose.
Notes
◈ Table areas declared using NODES behave like common data declared using the addition COMMON PART. They are shared by the programs of a program group. This feature should not be exploited due to the reasons outlined in Program Groups in External Procedure Calls.
◈ Table work areas declared using TABLES can be declared in subroutines and function modules, however this is not recommended. A table work area declared in a procedure is not local but belongs to the context of a master program. The table work area is visible as soon as the master program is declared and exists for the duration of the master program. In contrast to normal program-global data, the content of the table work areas declared in subroutines and function modules is stored temporarily when these subroutines and function modules are called. Assignments that were made during runtime of the procedure are preserved until the procedure is completed. When the procedure is exited, the table work areas are filled with the contents they contained when the procedure was called. Table work areas declared in procedures behave like global data to which the statement LOCAL is applied in the procedure.
◈ Always use NODES and not TABLES for interface work areas for logical databases. This makes it clear that they are nodes of logical databases.
◈ A CDS entity cannot be specified after TABLES. However, a CDS database view of a CDS view can be specified.
◈ The variant TABLES * is completely obsolete.
1.1.4 Special Declarations
These language elements should be used only by specialists with in-depth knowledge of the corresponding environment.
INFOTYPES
Syntax
INFOTYPES nnnn [NAME name]
[OCCURS n]
[MODE N|P]
[AS PERSON TABLE]
[VALID FROM intlim1 TO intlim2].
Additions
1. ... NAME name
2. ... OCCURS n
3. ... MODE N|P
4. ... AS PERSON TABLE
5. ... VALID FROM intlim1 TO intlim2
Effect
Declares an internal table for HR info types, forbidden in classes. Without the addition NAME, an internal table pnnnn or ppnnnn is created with the structure of the info type Pnnnn and a header. The name ppnnnn is used when the addition AS PERSON TABLE is specified, otherwise it is pnnnn.
As long as the addition MODE N is not specified, the statement INFOTYPES influences the behavior of the special logical databases PAP, PCH, PNP, and PNPCE of the human resources component HR by default and is the prerequisite for it working correctly.
A four-digit numeric key of an info type of SAP ERP component human resources (HR) must be specified for nnnn . Each info type is represented in the HR component by a special structure called Pnnnn in ABAP Dictionary. Each info type contains the character-like components BEGDA and ENDDA.
Notes
◈ The internal table created by the statement INFOTYPES can also be declared using the following (obsolete) statement sequence but then does not have any effect upon the special logical databases.
DATA BEGIN OF {pnnnn|ppnnnn|name} OCCURS { 10 | n }.
INCLUDE TYPE pnnnn.
DATA END OF {pnnnn|ppnnnn|name}
VALID BETWEEN {begda|intlim1} AND {endda|intlim2}.
◈ No internal tables with header lines can be declared in classes. For this reason, the statement INFOTYPES is forbidden here.
◈ In executable programs that are associated with the special logical databases PAP, PCH, PNP, and PNPCE of the human resources component, the statement INFOTYPES is still required and should only be used here.
◈ PNPCE is by far the most important of the logical databases PAP, PCH, PNP, and PNPCE. The logical data type PAP is hardly used anymore.
◈ Info types make it possible for an HR application to handle employee-related data effectively. The special statement PROVIDE is used for this.
◈ To ensure that the statement works with the logical databases correctly, it must be executed in the global declaration part and before the first operational statements of an executable program.
◈ The properties of the special logical databases determined by the statement INFOTYPES allow themselves to be changed using defined macros while the program is executed. For the logical database PNPCE these are the macros PNP_SET_INFTY_MODE_BY_NAME and PNP_SET_INFTY_MODE_BY_NUMBER for changing the mode, RP_SET_DATA_INTERVAL, RP_SET_DATA_INTERVAL_INFTY, and RP_SET_DATA_INTERVAL_ALL for setting the validity period.
Addition 1
... NAME name
Effect
Using the addition NAME, a name of up to 20 characters can be specified which is then used for the table instead of pnnnn or ppnnnn.
Addition 2
... OCCURS n
Effect
Without the addition OCCURS, the default memory requirements of the internal table are set to ten rows (see the addition INITIAL SIZE of the statement TYPES - TABLE OF). The addition OCCURS can be used to specify a numeric literal or a numeric constant n to determine a different initial memory requirement.
Addition 3
... MODE N|P
Addition 4
... AS PERSON TABLE
Effect
The additions affect the behavior of the special logical databases PAP, PCH, PNP, and PNPCE of the human resources component, where AS PERSON TABLE and MODE P only have an effect on the logical database PNPCE.
If the addition MODE N is not specified, the properties of the internal table are stored in an internal system table which is accessed in this logical database. If the statement INFOTYPES is executed without the addition MODE N in an executable program that is associated with one of these logical databases, the behavior is as follows:
Note
For more information see the documentation on the logical databases and particularly that of PNPCE.
Addition 5
... VALID FROM intlim1 TO intlim2
Effect
Without the addition VALID FROM, the components BEGDA and ENDDA of the info type Pnnnn are implicitly set as the interval boundaries for the obsolete form of the statement PROVIDE. With the addition VALID FROM , other flat character-like components intlim1 and intlim2 of the info type can be set as implicit interval boundaries.
These language elements should be used only by specialists with in-depth knowledge of the corresponding environment.
INFOTYPES
Syntax
INFOTYPES nnnn [NAME name]
[OCCURS n]
[MODE N|P]
[AS PERSON TABLE]
[VALID FROM intlim1 TO intlim2].
Additions
1. ... NAME name
2. ... OCCURS n
3. ... MODE N|P
4. ... AS PERSON TABLE
5. ... VALID FROM intlim1 TO intlim2
Effect
Declares an internal table for HR info types, forbidden in classes. Without the addition NAME, an internal table pnnnn or ppnnnn is created with the structure of the info type Pnnnn and a header. The name ppnnnn is used when the addition AS PERSON TABLE is specified, otherwise it is pnnnn.
As long as the addition MODE N is not specified, the statement INFOTYPES influences the behavior of the special logical databases PAP, PCH, PNP, and PNPCE of the human resources component HR by default and is the prerequisite for it working correctly.
A four-digit numeric key of an info type of SAP ERP component human resources (HR) must be specified for nnnn . Each info type is represented in the HR component by a special structure called Pnnnn in ABAP Dictionary. Each info type contains the character-like components BEGDA and ENDDA.
Notes
◈ The internal table created by the statement INFOTYPES can also be declared using the following (obsolete) statement sequence but then does not have any effect upon the special logical databases.
DATA BEGIN OF {pnnnn|ppnnnn|name} OCCURS { 10 | n }.
INCLUDE TYPE pnnnn.
DATA END OF {pnnnn|ppnnnn|name}
VALID BETWEEN {begda|intlim1} AND {endda|intlim2}.
◈ No internal tables with header lines can be declared in classes. For this reason, the statement INFOTYPES is forbidden here.
◈ In executable programs that are associated with the special logical databases PAP, PCH, PNP, and PNPCE of the human resources component, the statement INFOTYPES is still required and should only be used here.
◈ PNPCE is by far the most important of the logical databases PAP, PCH, PNP, and PNPCE. The logical data type PAP is hardly used anymore.
◈ Info types make it possible for an HR application to handle employee-related data effectively. The special statement PROVIDE is used for this.
◈ To ensure that the statement works with the logical databases correctly, it must be executed in the global declaration part and before the first operational statements of an executable program.
◈ The properties of the special logical databases determined by the statement INFOTYPES allow themselves to be changed using defined macros while the program is executed. For the logical database PNPCE these are the macros PNP_SET_INFTY_MODE_BY_NAME and PNP_SET_INFTY_MODE_BY_NUMBER for changing the mode, RP_SET_DATA_INTERVAL, RP_SET_DATA_INTERVAL_INFTY, and RP_SET_DATA_INTERVAL_ALL for setting the validity period.
Addition 1
... NAME name
Effect
Using the addition NAME, a name of up to 20 characters can be specified which is then used for the table instead of pnnnn or ppnnnn.
Addition 2
... OCCURS n
Effect
Without the addition OCCURS, the default memory requirements of the internal table are set to ten rows (see the addition INITIAL SIZE of the statement TYPES - TABLE OF). The addition OCCURS can be used to specify a numeric literal or a numeric constant n to determine a different initial memory requirement.
Addition 3
... MODE N|P
Addition 4
... AS PERSON TABLE
Effect
The additions affect the behavior of the special logical databases PAP, PCH, PNP, and PNPCE of the human resources component, where AS PERSON TABLE and MODE P only have an effect on the logical database PNPCE.
If the addition MODE N is not specified, the properties of the internal table are stored in an internal system table which is accessed in this logical database. If the statement INFOTYPES is executed without the addition MODE N in an executable program that is associated with one of these logical databases, the behavior is as follows:
- The logical database PAP fills the internal table for the event GET applicant.
- The logical database PCH fills the internal table for the event GET object.
- The logical database PNP fills the internal table for the event GET pernr.
- The behavior of the logical database PNPCE can additionally be controlled using the additions AS PERSON TABLE and MODE P:
- Without one of these additions, the table is filled with the event GET pernr. Only those data records are provided that fall in the specified evaluation period on the selection screen (this is a difference to the logical database PNP, which provides all data records by default). Alternatively, the macros RP_SET_DATA_INTERVAL, RP_SET_DATA_INTERVAL_INFTY, and RP_SET_DATA_INTERVAL_ALL defined in the logical database can be used to specify the data records that are to be provided.
- If only the addition AS PERSON TABLE is specified, the internal table is filled with the event GET group. All data records of all personnel numbers are provided that are in the included structure ALL_PERNRS of the structure group and for which there is authorization. Only those data records are provided which fall in the evaluation time period on the selection screen. Alternatively, the macros RP_SET_DATA_INTERVAL, RP_SET_DATA_INTERVAL_INFTY, and RP_SET_DATA_INTERVAL_ALL defined in the logical database can be used to specify the data records that are to be provided.
- If only the addition AS PERSON TABLE together with MODE P is specified, the internal table is filled with the event GET person. All data records of all personnel numbers are provided that are in the included structure ALL_PERNRS of the structure person. No authorization check is executed and all existing data records are displayed in every case regardless of how the evaluation period was set on the selection screen. Using the macros RP_SET_DATA_INTERVAL, RP_SET_DATA_INTERVAL_INFTY, and RP_SET_DATA_INTERVAL_ALL does not have any influence.
If the addition MODE N is specified, the table is not associated with the logical databases and is not filled with the GET events.
Note
For more information see the documentation on the logical databases and particularly that of PNPCE.
Addition 5
... VALID FROM intlim1 TO intlim2
Effect
Without the addition VALID FROM, the components BEGDA and ENDDA of the info type Pnnnn are implicitly set as the interval boundaries for the obsolete form of the statement PROVIDE. With the addition VALID FROM , other flat character-like components intlim1 and intlim2 of the info type can be set as implicit interval boundaries.
1.2 Classes and Interfaces
This section describes the definition of classes and interfaces and of their components. Classes and interfaces form the basis for ABAP Objects, the object-oriented part of the ABAP language. Classes and interfaces can be defined in ABAP programs of the following program types:
◈ In a class pool, the Class Builder tool in ABAP Workbench can be used to define exactly one global class of the class library, which can then be used in all other ABAP programs. In the global declaration part of a class pool, it is possible to define local data types, classes and interfaces to be used in the class pool and to make type groups known.
◈ In an interface pool, the Class Builder tool in ABAP Workbench is used to define exactly one global interface of the class library to be used in all other ABAP programs. In the global declaration part of an interface pool, it is not possible to define local data types, classes, and interfaces. Type groups can be made known. In interface pools, no other statements are allowed outside of the global interfaces.
◈ In all other ABAP programs, except type groups, it is possible to define local classes and interfaces to be used in the program itself.
1.2.1 ABAP Objects - Overview
ABAP Objects is the object-oriented part of ABAP.
ABAP Objects adds a complete set of language elements to ABAP (previously only a procedural language) that allow object-oriented programming. This object-oriented extension of ABAP builds on the previous range of languages, and is fully compatible with them. ABAP Objects can be used in existing programs, and the statements that can be used in ABAP Objects correspond to practically all of the remaining SAP language scope. However, specific obsolete language elements are not permitted in conjunction with ABAP objects due to a cleanup of the ABAP language.
ABAP Objects supports:
◇ Classes
◇ Interfaces
◇ Objects
◇ Object References
◇ Inheritance
Note
Package SABAP_DEMOS_CAR_RENTAL contains a complete example application written in ABAP Objects. Its presentation layer is implemented using a dynpro or Web Dynpro. The Web Dynpro calls interface methods that are implemented in a class and that, in turn, access classes that implement database accesses.
◎ Object Orientation
Object orientation (or, more correctly, object-oriented programming) is a problem-solving method that represents the real world in a series of software objects.
Object-oriented programming is based on a progamming model in which data and functions are unified in objects. The remaining language scope of ABAP mainly supports procedural programming, where the data is stored at other places than the objects and where programs that are modularized by procedures access this data.
This document defines a few general terms that are widely used in object orientation and in ABAP Objects.
Objects
Objects represent abstract or concrete objects of the real world. An object is a section of program code that has data (called attributes) and provides services called methods (sometimes also known as operations or functions). Methods typically work with private data in the object (attributes, also known as the object state), that are only visible within the object. This guarantees the internal consistency of the object, since the data is only changed by the methods, not by the user. This ensures that the object is consistent in itself.
Classes
Classes are program code that describes objects. Technically, an object is an instance of a class. In theory, you can create an infinite number of objects from a single class definition. Each instance of a class (object) has its own values for its attributes.
Object References
In a program, you identify and address objects using a unique object reference. They allow you to access the attributes and methods of an object.
In object-oriented programming, objects usually have the following characteristics:
Encapsulation
Objects restrict the external visibility of their resources (attributes and methods). Each object has an interface that determines how other objects or applications can use it. The implementation of the object is encapsulated (not visible outside the class).
Polymorphism
Methods with the same name can behave differently in different classes. In object-oriented programming, you can use interfaces to address methods with the same name in different objects. The form of address always remains the same, but the actual method implementation is class-specific, and can be different in each class.
Inheritance
You can derive a class from another class. A derived class (subclass) inherits the data and methods of its superclass. You can add new methods to a subclass, or redefine existing methods. Redefined methods have the same name and interface as the original method. Their classes are therefore polymorphous, too.
Benefits of Object Orientation
Object orientation has the following advantages:
◈ Complex software systems become easier to understand, since an object-oriented architecture resembles reality more closely than other programming techniques.
◈ Changes in object-oriented systems should be possible locally (at class level), without further changes being necessary in other parts of the system. This reduces the amount of maintenance required.
◈ Polymorphism and inheritance enable many individual components to be reused.
◈ Object-oriented systems require fewer revisions and less maintenance, because the majority of problems can be discovered and corrected in the design and development phases.
◈ Achieving these goals requires:
◈ Object-oriented programming languages
Object-oriented programming techniques do not necessarily require object-oriented programming languages. However, they do depend on the implementation of object-oriented constructions in the system kernel.
◈ Object-oriented tools
Object-oriented tools help you create object-oriented programs in object-oriented languages. They allow you to store and visualize your program objects and the relationship between them.
◈ Object-oriented modeling
Object-oriented modeling of a software system is the most important, most time consuming, and most difficult task required to achieve the above goals. Object-oriented design encompasses more than just object-oriented programming, and offers logical advantages that are independent of the eventual implementation.
◎ Definition of Classes and Interfaces
Classes and interfaces in ABAP Objects can be declared either globally or locally.
1. You define global classes and interfaces with the Class Builder in ABAP Workbench. They are stored centrally in the class library in the repository. From a technical perspective, global classes and interfaces are defined in class pools or interface pools. All ABAP programs in an AS ABAP can access these global classes and interfaces. Access is managed by the package check. Global classes and interfaces are stored in a namespace along with the data types of ABAP Dictionary.
2. You can define local classes and interfaces in all programs except interface pools and type groups. They can be used statically only in the defining program. Dynamic access from other programs is possible but not advisable. When you use a class in an ABAP program, the system first searches for a local class with the specified name. If it does not find one, it then looks for a global class. Otherwise, there is no difference between using global and local classes or interfaces.
If you are defining a local class that is only used in a single program, it is usually sufficient to define the outwardly visible components so that it fits into that program. Conversely, each global class is available throughout the system, which means that its public interface can only be specified with reference to data types that are themselves visible throughout the system.
The syntax for defining classes and interfaces is essentially the same for local and global classes and interfaces. The only difference is in the PUBLIC addition, which makes a distinction between the global classes and interfaces and local declarations.
Global classes and interfaces can be edited in the Class Builder, either in form-based or source-code based mode. In form-based mode, the Class Builder generates the relevant source code that can be accessed directly in source-code based mode.
Defining Classes
Classes consist of ABAP source code, enclosed in the ABAP statements CLASS ... ENDCLASS. A complete class definition consists of a declaration part and, if required, an implementation part.
The declaration part of a class named class consists of a statement block:
CLASS class DEFINITION.
...
ENDCLASS.
It contains the declaration for all components (attributes, methods, events) of the class. All the components of a class must be assigned explicitly to a visibility section (PUBLIC SECTION, PROTECTED SECTION, PRIVATE SECTION), which defines from where each component can be accessed. When you define local classes, the declaration part belongs to the global program data. You should therefore place it at the beginning of the program.
If you declare methods in the declaration part of a class, you must also write an implementation part for it. This consists of a further statement block:
CLASS class IMPLEMENTATION.
...
ENDCLASS.
The implementation part of a class contains the implementation of all methods of the class. Methods are procedures, that is, processing blocks of an ABAP program. The position of the implementation part in the source code is thus unimportant. For clarity, however, you should either put all the implementation parts of local classes at the end of the program, or directly after the relevant definition part. If you do the latter, note that you must then assign subsequent non-declarative statements explicitly to a processing block such as START-OF-SELECTION, so that they can be accessed.
Defining Interfaces
The definition of an intf interface is enclosed in the statements:
INTERFACE intf.
...
ENDINTERFACE.
The The definition contains the declaration for all components (attributes, methods, events) of the interface. In interfaces, you can define the same components as in classes. You cannot assign the components of an interface explicitly to a visibility section, because interface components always extend the public area of a class when they are implemented in it. Interfaces do not have an implementation part, since their methods are implemented in the class that implements the interface.
◎ Classes
The type of an object is known as its class. A class is an abstract representation of an object. Alternatively, it can be viewed as a set of instructions for building an object. The attributes of objects are defined by the components of the class, which describe the state and behavior of objects.
Global and Local Classes
Classes can be defined globally in the class library in the repository or locally in an ABAP program.
Global classes are encoded in a special ABAP program, a class pool, whereas local classes can be coded in almost every ABAP program. Global classes are visible in all ABAP programs. How they are used depends on the package check. Local classes can be used statically only in their own program. Dynamic access is also possible from other programs, although this is not recommended. When a global class is first used, the class pool is loaded to the internal session of the consumer. The local classes of a class pool can be used by the global classes of the pool.
Except for the storage type and the visibility, there are hardly any conceptual differences between global and local classes. One of the few differences is that in the public interface of a global class only references to public types are possible. These types are subdivided into global and local friends.
In principle, it also does not make any difference if a method of a local or global class is called. This is the reason why classes that are used by multiple programs should be created exclusively in the class library. Avoid reusing local classes by using include programs.
Components of Classes
The content of a class is composed of components. The components define the attributes of objects of a class. Each component is declared in the definition of the class in one of the four visibility sections that the interfaces define externally. Within a class, all its components are visible. All components are in the same namespace, which means that the names of all components in a class must be different.
The individual components are:
◈ Attributes
◈ Methods
◈ Events
◈ Types and constants
SAP makes a distinction between components of this type that are available on an instance-dependent basis for every object, and instance-independent components that are only available once in a class. The instance-dependent components are called instance components; the instance-independent components are known as static components.
In ABAP objects, classes can define the components listed above. Since all components that can be declared in classes can also be declared in interfaces, this description also applies to interfaces.
The components of classes can be accessed internally, and depending on the visibility, also from outside the class. If they are accessed externally, component selectors must be used for addressing.
1. Visibility Sections in Classes
The declaration part of a class can be split into up to four different visibility sections.
These sections define the external visibility of the class components and therefore the interfaces of the class for all consumers allowed by the package concept. Each component of a class must be explicitly assigned to one of the visibility sections. Only the friends of a class ignore the associated restrictions.
◈ Public visibility section
All components declared in the public visibility section defined using PUBLIC SECTION are accessible to all consumers as well as in the methods of all inheritors and the class itself. The public components of the class form the interface between the class and its consumers.
◈ Protected visibility section
All components declared in the protected visibility section defined with PROTECTED SECTION are accessible in the methods of all inheritors and in the class itself. Protected components form a special interface between a class and its subclasses.
◈ Private visibility section
All components declared in the private visibility section defined with PRIVATE SECTION are only accessible in the class itself, and are also not visible to the inheritors. The private components therefore do not form an interface to the consumers of the class.
The following table summarizes the visibilities of a class:
Visible for | PUBLIC SECTION | PROTECTED SECTION | PRIVATE SECTION |
Same class and its friends | x | x | x |
Any subclasses | x | x | - |
Any repository objects | x | - | - |
Note
A subclass can generally never access the protected components of a subclass from a different branch in the inheritance hierarchy, even if they are inherited from a common superclass. This rule can only be lifted by a friendship.
Encapsulation
The three visibility sections form the basis for the important feature of encapsulation in ABAP Objects. When declaring a class, as few components as possible must be declared in the public section and these public components must be designed with care. The public components of global classes may not be changed once the class has been released.
Note
The class is the smallest encapsulation unit in ABAP Objects. A method can therefore use all components of all instances of the same class, except for the components of its own class. An exception to this rule are subclasses that cannot access the private components of superclasses, if they are not their friends.
Example
In method m1 of class c1, reference variables of static type c1 can be used to access the protected attribute a11 and the private attribute a12 of any objects of c1. In method m2 of subclass c2, reference variables of static type c1 or c2 can similarly be used to access the protected attribute a11. It is not possible to access the private attribute of the superclass with either reference variable.
CLASS c1 DEFINITION.
PUBLIC SECTION.
METHODS m1.
PROTECTED SECTION.
DATA a11 TYPE i.
PRIVATE SECTION.
DATA a12 TYPE i.
ENDCLASS.
CLASS c1 IMPLEMENTATION.
METHOD m1.
DATA lref1 TYPE REF TO c1.
lref1->a11 = 0. "OK
lref1->a12 = 0. "OK
ENDMETHOD.
ENDCLASS.
CLASS c2 DEFINITION INHERITING FROM c1.
PUBLIC SECTION.
METHODS m2.
ENDCLASS.
CLASS c2 IMPLEMENTATION.
METHOD m2.
DATA: lref1 TYPE REF TO c1,
lref2 TYPE REF TO c2.
lref1->a11 = 0. "OK
lref2->a11 = 0. "OK
"lref1->a12 = 0. "Syntax error, access to a11 not permitted
"lref2->a12 = 0. "Syntax error, a12 not visible
ENDMETHOD.
ENDCLASS.
2. Class Attributes
Attributes are internal data objects of any ABAP data type within a class. The content of the attributes specifies the state of the object. Reference variables can also be defined, which can then be used to create and address objects. This allows objects to be accessed within classes.
Attributes are defined in the declaration part of a class. Public attributes are completely visible from outside the class and as such are part of the interface between objects and their consumers. To encapsulate the state of the object, protected, package-visible, or private attributes must be used. The modifiability of non-private attributes can also be restricted using the addition READ-ONLY in the declaration.
◈ Instance Attributes
◈ Static Attributes
◈ Data Types of Attributes
◈ Boxed Components
Instance Attributes
The content of instance attributes forms the instance-specific state of the object. Instance attributes are declared using the DATA statement. The addition COMMON PART cannot be used in classes.
Static Attributes
The content of static attributes forms the instance-independent state of the object, which is valid for all instances of the class. Static attributes are available once for each class. They are declared using the statement CLASS-DATA and are retained throughout the entire runtime. All the objects within a class can access its static attributes. Changes to a static attribute in an object are visible to all other objects within that class.
Data Types of Attributes
The data types of all attributes including the instance attributes and in particular the bound data types belong to the static properties of a class. Therefore, in a LIKE addition, the class component selector or reference variables can be used to refer to visible attributes of a class, without first creating an object. In this way, the access to the properties of the public static attributes of global classes is possible in each program.
Example
Reference to the data type of an instance attribute attr of a global class cl_global.
DATA dref TYPE REF TO cl_global.
DATA: f1 LIKE cl_global=>attr,
f2 LIKE dref->attr.
Boxed Components
Attributes declared as structures can be declared as static boxes using the addition BOXED, like substructures of nested structures. In static boxes, initial value sharing causes less memory to be used for little used structures of much used objects. A static box used as a boxed component is a deep component administered using an internal reference, like strings and internal tables.
Attributes are internal data objects of any ABAP data type within a class. The content of the attributes specifies the state of the object. Reference variables can also be defined, which can then be used to create and address objects. This allows objects to be accessed within classes.
Attributes are defined in the declaration part of a class. Public attributes are completely visible from outside the class and as such are part of the interface between objects and their consumers. To encapsulate the state of the object, protected, package-visible, or private attributes must be used. The modifiability of non-private attributes can also be restricted using the addition READ-ONLY in the declaration.
◈ Instance Attributes
◈ Static Attributes
◈ Data Types of Attributes
◈ Boxed Components
Instance Attributes
The content of instance attributes forms the instance-specific state of the object. Instance attributes are declared using the DATA statement. The addition COMMON PART cannot be used in classes.
Static Attributes
The content of static attributes forms the instance-independent state of the object, which is valid for all instances of the class. Static attributes are available once for each class. They are declared using the statement CLASS-DATA and are retained throughout the entire runtime. All the objects within a class can access its static attributes. Changes to a static attribute in an object are visible to all other objects within that class.
Data Types of Attributes
The data types of all attributes including the instance attributes and in particular the bound data types belong to the static properties of a class. Therefore, in a LIKE addition, the class component selector or reference variables can be used to refer to visible attributes of a class, without first creating an object. In this way, the access to the properties of the public static attributes of global classes is possible in each program.
Example
Reference to the data type of an instance attribute attr of a global class cl_global.
DATA dref TYPE REF TO cl_global.
DATA: f1 LIKE cl_global=>attr,
f2 LIKE dref->attr.
Boxed Components
Attributes declared as structures can be declared as static boxes using the addition BOXED, like substructures of nested structures. In static boxes, initial value sharing causes less memory to be used for little used structures of much used objects. A static box used as a boxed component is a deep component administered using an internal reference, like strings and internal tables.
3. Methods of Classes
Methods are internal procedures of a class that determine the behavior of an object. They can access all the attributes of all instances of their class and can therefore change the status of an object. Methods have a parameter interface, used by the system to pass values to them when they are called, and by which they can return values to the caller. The private attributes of a class can only be changed using methods of the same class.
◈ Definition
◈ Instance Methods
◈ Static Methods
◈ Constructors
◈ Functional Methods
◈ Optional Methods
◈ Special Methods
◈ AMDP Methods
◈ Kernel Methods
Definition
A method meth is declared in the declaration part of a class using the statements METHODS and CLASS-METHODS and implemented in the implementation part of the class using the processing block
METHOD meth.
...
ENDMETHOD.
. As in all procedures, local data types and data objects can be declared in methods. Methods are called statically using the expression meth( ... ) or dynamically using the statement CALL METHOD (Dynamic Invoke).
Instance Methods
Instance methods are declared using the METHODS statement. They can access all the attributes of a class and can trigger all its events.
Static Methods
Static methods are declared using the CLASS-METHODS statement. This statement can access static attributes of a class and is can trigger static events only.
Constructors
As well as the normal methods that are called explicitly, there are two special methods called constructor and class_constructor, which are called automatically when an object is created or when a class component is accessed for the first time.
Functional Methods
Functional methods are methods with precisely one RETURNING parameter and any number of other formal parameters. Functional methods cannot just be called as standalone statements, but also as functional method calls in operand positions for functions and expressions. Here they can be also be combined as method chainings.
Optional Methods
In interfaces, methods can be made optional using the addition DEFAULT of the statements METHODS and CLASS-METHODS. An optional interface method does not need to be implemented explicitly in a class when an interface is implemented. Instead, a default behavior is specified for calls of non-implemented methods in the definition. DEFAULT IGNORE calls an empty method and DEFAULT FAIL raises an exception.
Special Methods
AMDP Methods
AMDP methods are implemented using the addition BY DATABASE PROCEDURE or BY DATABASE FUNCTION in a database-specific language as ABAP Managed Database Procedures and executed in the database system.
Kernel Methods
For internal use, kernel methods are implemented in the kernel using the addition BY KERNEL MODULE.
● Interface Parameters in Methods
Interface parameters in methods are input parameters (IMPORTING, CHANGING parameters) and output parameters (EXPORTING, CHANGING, RETURNING parameters). In declarations with the statements
◈ METHODS
◈ CLASS-METHODS
◈ EVENTS
◈ CLASS-EVENTS
the following attributes are determined:
Passing parameters by reference or by value
With the exception of the return value (RETURNING parameters), parameters can be passed both by value or reference. Passing by reference is standard with methods. If only a name p is specified in the parameter declaration, the parameter is passed implicitly as a reference. If a VALUE(p) is specified instead, then the parameter is passed as a value. The return value may only be passed as a value. Passing by reference can also be explicitly specified with other parameters using REFERENCE(p). An IMPORTING parameter transferred by reference, cannot be changed in the method.
Typing parameters
All parameters must be typed during declaration using the addition TYPE or the addition LIKE. The following entries are allowed after TYPE as parameter types:
Optional parameters
All input parameters (IMPORTING, CHANGING parameters) can be defined in the declaration as optional parameters using the additions OPTIONAL or DEFAULT. These parameters must not necessarily be transfered when the method is called. With the addition OPTIONAL your parameter remains initialized according to type, while the addition DEFAULT allows you to enter a start value.
● The C Destructor
A destructor is a special method which is called automatically when an object is deleted. Destructors can be used to release resources used by the object that are not included in the Garbage Collection. Currently, ABAP Objects does not include a destructor, in which a regular ABAP processing block can be programmed.
For special cases and for internal use only, the predefined instance method destructor can be declared in the public visibility section of a class:
CLASS class DEFINITION.
PUBLIC SECTION.
METHODS destructor [NOT AT END OF MODE].
...
ENDCLASS.
Only one statement can currently be used in the implementation of the method destructor:
CLASS class IMPLEMENTATION.
METHOD destructor.
SYSTEM-CALL c-destructor 'name' USING attr1 attr2 ...
ENDMETHOD.
ENDCLASS.
This means that the destructor makes it possible to call a C routine name when an object is deleted. The routine must exist in the ABAP kernel so that no syntax error occurs.
When the optional addition NOT AT END OF MODE is used, the destructor is not executed if the internal mode is closed anyway. Usually a destructor is also executed at the end of a mode and should mainly be used to release external resources involved that are not released automatically when the mode is closed.
When the C routine is called, an attribute attr1, attr2, ... of the class of any complex data type can be passed on to the routine. If multiple parameters are to be passed, an appropriate data type must be defined.
During the lifetime of an internal mode, the time when the method destructor is executed depends on when the Garbage Collector is started. When an internal mode is closed, the destructors that are not declared using the addition NOT AT END OF MODE are executed for all objects. In cases of inheritance, the destructors of the subclasses are executed before the destructors of the superclasses.
● Kernel Methods
For internal use, kernel methods can be implemented in the ABAP kernel instead of in the ABAP language.
Introduction
Kernel methods allow ABAP kernel functions implemented in C or C++ to be called directly. Kernel methods replace the previous concepts of C calls and system calls. No new C calls or system calls need to be introduced.
Kernel methods offer the same checks and security features as regular ABAP methods. Except for the Constructors and the C Destructor, all ABAP methods can be implemented as kernel methods. An ABAP method can still be redefined as a kernel method and a kernel method can still be redefined as an ABAP method within a path of the inheritance hierarchy.
For C developers who want to implement a kernel method, an API is available that allows simple, high-performance, and secure access to arguments. Class-based exceptions also continue to be supported.
Defining Kernel Methods
Declaration in ABAP
A kernel method is declared in the same way as a regular ABAP method, in Class Builder or in the declaration part of a local class. Whether a method is implemented as a kernel method is not important for the declaration. In ABAP, this means that a kernel method can be used just like a regular ABAP method.
Implementation in ABAP
A method is specified as a kernel method in the implementation part of the class using the optional addition BY KERNEL MODULE kmod1 kmod2 ... of the statement METHOD. kmod1, kmod2, ... are the names of kernel modules that implement the method. The ABAP implementation of a kernel method must be empty, which means that there cannot be any ABAP statements between METHOD and ENDMETHOD:
METHOD meth BY KERNEL MODULE kmod1 kmod2 ...
ENDMETHOD.
Constructors and the C Destructor cannot be implemented as kernel methods. There is a separate mechanism for the C Destructor.
After KERNEL MODULE, a list of kernel modules kmod1, kmod2, ... can be specified. Currently, only C functions of the kernel can be specified for kmod1, kmod2, ... The list after KERNEL MODULE is evaluated by the compiler from left to right. The first kernel module in the list that is registered in the kernel (see below) is used in the generation.
If no valid kernel module is found in the list, a syntax error occurs. There are still two standard C functions that can appear at the end of the list: FAIL and IGNORE. If one of these functions is specified at the end of the list, a syntax error is avoided if the previous list does not contain a valid module. IGNORE is used to ignore the call of a kernel method of this type (behavior as in an empty ABAP implementation) and, in the case of FAIL, a handleable exception of the class CX_SY_DYN_CALL_ILLEGAL_METHOD is raised.
Examples
METHOD meth BY KERNEL MODULE xx_impl_630 xx_impl_620 xx_impl_610.
First, the kernel is searched for xx_impl_630. The kernel is then searched for xx_impl_620, and finally for xx_impl_610. If none of these functions are found, a syntax error is raised.
METHOD meth BY KERNEL MODULE xx_impl_630 xx_impl_620 FAIL.
First, the kernel is searched for xx_impl_630. Then the kernel is searched for xx_impl_620. If neither of these functions are found, a syntax error is not raised; a handleable exception of the class CX_SY_DYN_CALL_ILLEGAL_METHOD is raised instead, when the method is called.
METHOD meth BY KERNEL MODULE xx_impl_620 xx_impl_610 IGNORE.
First, the kernel is searched for xx_impl_620. Then the kernel is searched for xx_impl_610. If none of the functions are found, a syntax error is not raised; the empty ABAP implementation is called instead, when the method is called.
Implementation in the Kernel
Currently, only C functions can be used as kernel modules of kernel methods. The C functions can have any position in the kernel. No special includes from the ABAP runtime environment are required for implementing the C function. The C functions must have a specific interface. The interface itself is wrapped by a macro called ARGUMENTS. All required definitions and prototypes are in the include //src/include/abkmeth.h. This is the only include needed for defining C functions for kernel methods.
Since C functions can be defined in C and C++ , externC must be used in C++:
#include "abkmeth.h"
...
externC void name_of_cmodule( ARGUMENTS )
{
...
}
A C function that implements a kernel method must be registered for the kernel method. If, after METHOD meth BY KERNEL MODULE, the name of a C function is specified that was not registered for the kernel method, a syntax error occurs (as mentioned above). Multiple C functions can be registered for one kernel method. The order of the kernel modules kmod1, kmod2, ... specified in the list after METHOD meth BY KERNEL MODULE defines which of the registered C functions is used. This allows downward-compatible further development of kernel methods.
To make changes to the registration active, the destination lib of the project krn/runt must be recompiled and the kernel relinked.
Registration
C functions are registered in the signature file //src/krn/runt/abkmeth.sig using the following syntax for kernel methods (all ABAP IDs must be specified in uppercase letters):
KERNEL_METHOD("CLASS","METH", cfunc,argcnt)
This definition registers the C function cfunc for the kernel method meth of a global class class. The C function expects a number of argcnt arguments.
Kernel methods of local classes in class pools or other ABAP programs are registered using the following macros:
KERNEL_METHOD_CLASS_LOCAL("GCLASS","CLASS","METH",cmodule,argcnt)
KERNEL_METHOD_PROGRAM_LOCAL("PROG","CLASS","METH",cmodule,argcnt)
The technique is the same as with KERNEL_METHOD, except that the global class gclass must be specified for local classes in class pools and the program prog for program-local classes.
Registering Arguments
All ABAP data objects (such as parameters, attributes, or global data) that are to be accessed in C functions for kernel methods, are handled as arguments of the C function.
The argument list of a C function for a kernel method is not limited to the interface parameters of the ABAP method and does not have to contain these completely. Before arguments within C functions are accessed for kernel methods, these arguments must be registered.
The argcnt arguments must be registered immediately after the C function is registered using KERNEL_METHOD. A single argument is defined (registered) using one of the following macros:
ARGUMENT_basetype(index,"name",type_kind,"type",read_write)
ARGUMENT_[C|N|X](index,"name",type_kind,"type",read_write,length)
ARGUMENT_P(index,"name",type_kind,"type",read_write,length,decimals)
ARGUMENT_STRUCT(index,"name",type_kind,"type",read_write,ctype)
These macros define an argument with the name name and an index index.
basetype must be used to assign the type of the ABAP data object in accordance with the following table. If the basetype is C, N, X, P, or STRUCT, more parameters must be specified than for other types.
Methods are internal procedures of a class that determine the behavior of an object. They can access all the attributes of all instances of their class and can therefore change the status of an object. Methods have a parameter interface, used by the system to pass values to them when they are called, and by which they can return values to the caller. The private attributes of a class can only be changed using methods of the same class.
◈ Definition
◈ Instance Methods
◈ Static Methods
◈ Constructors
◈ Functional Methods
◈ Optional Methods
◈ Special Methods
◈ AMDP Methods
◈ Kernel Methods
Definition
A method meth is declared in the declaration part of a class using the statements METHODS and CLASS-METHODS and implemented in the implementation part of the class using the processing block
METHOD meth.
...
ENDMETHOD.
. As in all procedures, local data types and data objects can be declared in methods. Methods are called statically using the expression meth( ... ) or dynamically using the statement CALL METHOD (Dynamic Invoke).
Instance Methods
Instance methods are declared using the METHODS statement. They can access all the attributes of a class and can trigger all its events.
Static Methods
Static methods are declared using the CLASS-METHODS statement. This statement can access static attributes of a class and is can trigger static events only.
Constructors
As well as the normal methods that are called explicitly, there are two special methods called constructor and class_constructor, which are called automatically when an object is created or when a class component is accessed for the first time.
Functional Methods
Functional methods are methods with precisely one RETURNING parameter and any number of other formal parameters. Functional methods cannot just be called as standalone statements, but also as functional method calls in operand positions for functions and expressions. Here they can be also be combined as method chainings.
Optional Methods
In interfaces, methods can be made optional using the addition DEFAULT of the statements METHODS and CLASS-METHODS. An optional interface method does not need to be implemented explicitly in a class when an interface is implemented. Instead, a default behavior is specified for calls of non-implemented methods in the definition. DEFAULT IGNORE calls an empty method and DEFAULT FAIL raises an exception.
Special Methods
AMDP Methods
AMDP methods are implemented using the addition BY DATABASE PROCEDURE or BY DATABASE FUNCTION in a database-specific language as ABAP Managed Database Procedures and executed in the database system.
Kernel Methods
For internal use, kernel methods are implemented in the kernel using the addition BY KERNEL MODULE.
● Interface Parameters in Methods
Interface parameters in methods are input parameters (IMPORTING, CHANGING parameters) and output parameters (EXPORTING, CHANGING, RETURNING parameters). In declarations with the statements
◈ METHODS
◈ CLASS-METHODS
◈ EVENTS
◈ CLASS-EVENTS
the following attributes are determined:
Passing parameters by reference or by value
With the exception of the return value (RETURNING parameters), parameters can be passed both by value or reference. Passing by reference is standard with methods. If only a name p is specified in the parameter declaration, the parameter is passed implicitly as a reference. If a VALUE(p) is specified instead, then the parameter is passed as a value. The return value may only be passed as a value. Passing by reference can also be explicitly specified with other parameters using REFERENCE(p). An IMPORTING parameter transferred by reference, cannot be changed in the method.
Typing parameters
All parameters must be typed during declaration using the addition TYPE or the addition LIKE. The following entries are allowed after TYPE as parameter types:
Optional parameters
All input parameters (IMPORTING, CHANGING parameters) can be defined in the declaration as optional parameters using the additions OPTIONAL or DEFAULT. These parameters must not necessarily be transfered when the method is called. With the addition OPTIONAL your parameter remains initialized according to type, while the addition DEFAULT allows you to enter a start value.
● The C Destructor
A destructor is a special method which is called automatically when an object is deleted. Destructors can be used to release resources used by the object that are not included in the Garbage Collection. Currently, ABAP Objects does not include a destructor, in which a regular ABAP processing block can be programmed.
For special cases and for internal use only, the predefined instance method destructor can be declared in the public visibility section of a class:
CLASS class DEFINITION.
PUBLIC SECTION.
METHODS destructor [NOT AT END OF MODE].
...
ENDCLASS.
Only one statement can currently be used in the implementation of the method destructor:
CLASS class IMPLEMENTATION.
METHOD destructor.
SYSTEM-CALL c-destructor 'name' USING attr1 attr2 ...
ENDMETHOD.
ENDCLASS.
This means that the destructor makes it possible to call a C routine name when an object is deleted. The routine must exist in the ABAP kernel so that no syntax error occurs.
When the optional addition NOT AT END OF MODE is used, the destructor is not executed if the internal mode is closed anyway. Usually a destructor is also executed at the end of a mode and should mainly be used to release external resources involved that are not released automatically when the mode is closed.
When the C routine is called, an attribute attr1, attr2, ... of the class of any complex data type can be passed on to the routine. If multiple parameters are to be passed, an appropriate data type must be defined.
During the lifetime of an internal mode, the time when the method destructor is executed depends on when the Garbage Collector is started. When an internal mode is closed, the destructors that are not declared using the addition NOT AT END OF MODE are executed for all objects. In cases of inheritance, the destructors of the subclasses are executed before the destructors of the superclasses.
● Kernel Methods
For internal use, kernel methods can be implemented in the ABAP kernel instead of in the ABAP language.
Introduction
Kernel methods allow ABAP kernel functions implemented in C or C++ to be called directly. Kernel methods replace the previous concepts of C calls and system calls. No new C calls or system calls need to be introduced.
Kernel methods offer the same checks and security features as regular ABAP methods. Except for the Constructors and the C Destructor, all ABAP methods can be implemented as kernel methods. An ABAP method can still be redefined as a kernel method and a kernel method can still be redefined as an ABAP method within a path of the inheritance hierarchy.
For C developers who want to implement a kernel method, an API is available that allows simple, high-performance, and secure access to arguments. Class-based exceptions also continue to be supported.
Defining Kernel Methods
Declaration in ABAP
A kernel method is declared in the same way as a regular ABAP method, in Class Builder or in the declaration part of a local class. Whether a method is implemented as a kernel method is not important for the declaration. In ABAP, this means that a kernel method can be used just like a regular ABAP method.
Implementation in ABAP
A method is specified as a kernel method in the implementation part of the class using the optional addition BY KERNEL MODULE kmod1 kmod2 ... of the statement METHOD. kmod1, kmod2, ... are the names of kernel modules that implement the method. The ABAP implementation of a kernel method must be empty, which means that there cannot be any ABAP statements between METHOD and ENDMETHOD:
METHOD meth BY KERNEL MODULE kmod1 kmod2 ...
ENDMETHOD.
Constructors and the C Destructor cannot be implemented as kernel methods. There is a separate mechanism for the C Destructor.
After KERNEL MODULE, a list of kernel modules kmod1, kmod2, ... can be specified. Currently, only C functions of the kernel can be specified for kmod1, kmod2, ... The list after KERNEL MODULE is evaluated by the compiler from left to right. The first kernel module in the list that is registered in the kernel (see below) is used in the generation.
If no valid kernel module is found in the list, a syntax error occurs. There are still two standard C functions that can appear at the end of the list: FAIL and IGNORE. If one of these functions is specified at the end of the list, a syntax error is avoided if the previous list does not contain a valid module. IGNORE is used to ignore the call of a kernel method of this type (behavior as in an empty ABAP implementation) and, in the case of FAIL, a handleable exception of the class CX_SY_DYN_CALL_ILLEGAL_METHOD is raised.
Examples
METHOD meth BY KERNEL MODULE xx_impl_630 xx_impl_620 xx_impl_610.
First, the kernel is searched for xx_impl_630. The kernel is then searched for xx_impl_620, and finally for xx_impl_610. If none of these functions are found, a syntax error is raised.
METHOD meth BY KERNEL MODULE xx_impl_630 xx_impl_620 FAIL.
First, the kernel is searched for xx_impl_630. Then the kernel is searched for xx_impl_620. If neither of these functions are found, a syntax error is not raised; a handleable exception of the class CX_SY_DYN_CALL_ILLEGAL_METHOD is raised instead, when the method is called.
METHOD meth BY KERNEL MODULE xx_impl_620 xx_impl_610 IGNORE.
First, the kernel is searched for xx_impl_620. Then the kernel is searched for xx_impl_610. If none of the functions are found, a syntax error is not raised; the empty ABAP implementation is called instead, when the method is called.
Implementation in the Kernel
Currently, only C functions can be used as kernel modules of kernel methods. The C functions can have any position in the kernel. No special includes from the ABAP runtime environment are required for implementing the C function. The C functions must have a specific interface. The interface itself is wrapped by a macro called ARGUMENTS. All required definitions and prototypes are in the include //src/include/abkmeth.h. This is the only include needed for defining C functions for kernel methods.
Since C functions can be defined in C and C++ , externC must be used in C++:
#include "abkmeth.h"
...
externC void name_of_cmodule( ARGUMENTS )
{
...
}
A C function that implements a kernel method must be registered for the kernel method. If, after METHOD meth BY KERNEL MODULE, the name of a C function is specified that was not registered for the kernel method, a syntax error occurs (as mentioned above). Multiple C functions can be registered for one kernel method. The order of the kernel modules kmod1, kmod2, ... specified in the list after METHOD meth BY KERNEL MODULE defines which of the registered C functions is used. This allows downward-compatible further development of kernel methods.
To make changes to the registration active, the destination lib of the project krn/runt must be recompiled and the kernel relinked.
Registration
C functions are registered in the signature file //src/krn/runt/abkmeth.sig using the following syntax for kernel methods (all ABAP IDs must be specified in uppercase letters):
KERNEL_METHOD("CLASS","METH", cfunc,argcnt)
This definition registers the C function cfunc for the kernel method meth of a global class class. The C function expects a number of argcnt arguments.
Kernel methods of local classes in class pools or other ABAP programs are registered using the following macros:
KERNEL_METHOD_CLASS_LOCAL("GCLASS","CLASS","METH",cmodule,argcnt)
KERNEL_METHOD_PROGRAM_LOCAL("PROG","CLASS","METH",cmodule,argcnt)
The technique is the same as with KERNEL_METHOD, except that the global class gclass must be specified for local classes in class pools and the program prog for program-local classes.
Registering Arguments
All ABAP data objects (such as parameters, attributes, or global data) that are to be accessed in C functions for kernel methods, are handled as arguments of the C function.
The argument list of a C function for a kernel method is not limited to the interface parameters of the ABAP method and does not have to contain these completely. Before arguments within C functions are accessed for kernel methods, these arguments must be registered.
The argcnt arguments must be registered immediately after the C function is registered using KERNEL_METHOD. A single argument is defined (registered) using one of the following macros:
ARGUMENT_basetype(index,"name",type_kind,"type",read_write)
ARGUMENT_[C|N|X](index,"name",type_kind,"type",read_write,length)
ARGUMENT_P(index,"name",type_kind,"type",read_write,length,decimals)
ARGUMENT_STRUCT(index,"name",type_kind,"type",read_write,ctype)
These macros define an argument with the name name and an index index.
basetype must be used to assign the type of the ABAP data object in accordance with the following table. If the basetype is C, N, X, P, or STRUCT, more parameters must be specified than for other types.
basetype | ABAP Data Type | Type in C |
C | c with specified length | SAP_CHAR (*) [Length] |
C_GENERIC | c without specified length | SAP_CHAR* |
X | x with specified length | SAP_RAW (*) [Length] |
X_GENERIC | x without specified length | SAP_RAW* |
N | n with specified length | SAP_CHAR (*) [Length] |
N_GENERIC | n without specified length | SAP_CHAR* |
P | p with specified length and decimals | SAP_BCD (*) [Length] |
P_GENERIC | p without specified length and decimals | SAP_BCD* |
D | d | SAP_DATE* |
T | t | SAP_TIME* |
I | i | SAP_INT* |
INT1 | b | SAP_INT1* |
INT2 | s | SAP_SHORT* |
INT8 | int8 | SAP_LLONG* |
F | f | SAP_DOUBLE* |
DECFLOAT16 | decfloat16 | DecFloat16 |
DECFLOAT34 | decfloat34 | DecFloat34 |
STRING | string | StrRef* |
XSTRING | xstring | StrRef* |
TABLE | All table types | TABH_REF* |
OBJ_REF | All object references | ObjRef* |
DATA_REF | All data references | FldRef* |
STRUCT | All structure types | Registered type ctype* |
ANY | any | void* |
DATA | data | void* |
SIMPLE | simple | void* |
CSEQUENCE | csequence | void* |
XSEQUENCE | xsequence | void* |
NUMERIC | numeric | void* |
CLIKE | clike | SAP_CHAR* |
C_POINTER | %_c_pointer | void** |
The macro parameters have the following meanings:
◈ name is the ID for any ABAP data object in uppercase letters that could also be used in an ABAP implementation of the kernel method. In particular, the ID can contain links with component selectors, for example me->attr or struc-comp.
◈ index is a sequential number from 1 to argcnt. The arguments are accessed using this index.
◈ For type_kind, either TYPE or TYPE_REF_TO can be specified.
◈ type is the ID for any ABAP data type in uppercase letters that could also be used in an ABAP implementation of the kernel method. type_kind and type are used to check the interface of the kernel method in ABAP.
◈ For read_write, either READ or WRITE can be specified. This defines whether reads or writes can be performed on the argument and this setting is evaluated in the access macros.
◈ length is used to specify the length of all ABAP data types with a generic length in the case of ARGUMENT_[C|N|X|P]. In characters for c and n and in bytes for x and p.
◈ When using ARGUMENT_P, decimals must be used to specify the number of decimal places.
◈ When using ARGUMENT_STRUCT, ctype must be used to specify a suitable C type. This type should be generated from an ABAP type definition using saphfile.
Accessing Arguments
After registering the arguments, the following macros can be used to access them within the C function. With the exception of the direct access to the data control block, the access macros do not require any includes from the ABAP runtime environment.
ARGUMENT_basetype_READ(index,"name");
This macro returns the read address of an argument with the type const ctype, where ctype is defined by basetype according to the above table. The index and name of the argument must be passed. Additional parameters must be specified for the generic types (see below). Only the index is needed to access the argument. However, to make the C function more legible and to ensure that additional consistency checks can be executed, the name must also be specified. If the kernel is compiled in debugging mode, the system executes a consistency check between index and name; the specified C type and ABAP type of the argument are also checked. In the case of an error, an appropriate ABAP runtime error is triggered (KMETH_INVALID_ARGUMENT_ID, KMETH_INVALID_ARGUMENT_NAME, or KMETH_INVALID_CTYPE_LENG). No checks are made in the optimized kernel.
ARGUMENT_basetype_WRITE(index,"name");
This macro has the same semantics as ARGUMENT_basetype_READ. However, the system returns the write address. The system also checks whether the argument was defined as a write argument. If a write is performed on a read-only argument (for example, a constant), this triggers the ABAP runtime error KMETH_ARGUMENT_READ_ONLY.
ARGUMENT_[C|N]_READ(index,"name",lengthU);
ARGUMENT_[C|N]_WRITE(index,"name",lengthU);
ARGUMENT_X_READ(index,"name",lengthR);
ARGUMENT_X_WRITE(index,"name",lengthR);
If these macros are used, the expected length in bytes lengthR or in characters lengthU must be specified for the generic types c, x, and n.
ARGUMENT_P_READ(index,"name",lengthR,decimals);
ARGUMENT_P_WRITE(index,"name",lengthR,decimals);
If these macros are used, the expected length in bytes (lengthR) and the number of decimal places (decimals) must be specified for the generic type p.
ARGUMENT_[C_GENERIC|N_GENERIC|CLIKE]_READ(index,"name",size_tU);
ARGUMENT_[C_GENERIC|N_GENERIC|CLIKE]_WRITE(index,"name",size_tU);
ARGUMENT_X_GENRIC_READ(index,"name",size_tR);
ARGUMENT_X_GENERIC_WRITE(index,"name",size_tR);
When using these macros, a variable of the type size_tU or size_tR, containing the length in bytes or characters, must be specified for the types C_GENERIC, X_GENERIC, N_GENERIC, and CLIKE.
ARGUMENT_P_GENERIC_READ(index,"name",size_tR,decimals);
ARGUMENT_P_GENERIC_WRITE(index,"name",size_tR,decimals);
If these macros are used, a variable decimals (for the decimal places) as well as the length size_tR must be specified for the type P_GENERIC.
ARGUMENT_STRUCT_READ(index,"name",ctype);
ARGUMENT_STRUCT_READ(index,"name",ctype);
If these macros are used, a suitable C typectype must be specified for all structured types STRUCT.
ARGUMENT_C_POINTER(index,"name");
This macro is available specifically for the type %_c_pointer. This type is a special internal ABAP type that has exactly the byte length of a C pointer (4, 8, or 16 bytes, depending on platform). The type is always mapped to the predefined ABAP type x. The macros for the type X or X_GENERIC are not used due to the variable length and platform-dependency.
ARGUMENT_IS_SUPPLIED(index,"name");
This macro has the same semantics as the predicate expression IS SUPPLIED in ABAP. The same consistency checks are executed as for ARGUMENT_READ.
ARGUMENT_DATA(index,"name",ctype);
This macro returns the data control block with the C type const DATA *. The same consistency checks are executed as for ARGUMENT_READ. The macro is only active if the include //src/include/abdata.h of the ABAP runtime environment was included.
Raising Exceptions
C functions that implement kernel method can raise class-based exceptions.
Registering Exceptions
The relevant global exception classes must be registered with an extension of //src/include/abexcpc.h. Local exception classes cannot be registered.
The exception class is declared in //src/include/abexcpc.h and any text IDs are defined:
//src/include/abexcpc.h
...
CX_ABSTR (CX_..., "CX_...")
CX_TXTID (CX_..._bar, CX_..., "BAR") /* special text for class */
...
Classes can also be declared with their standard text only:
//src/include/abexcpc.h
...
CX_CLASS (CX_..., "CX_...") /* class with standard text */
...
The exact documentation is in the file //src/include/abexcpc.h.
The file //src/include/abexcpa.h must be expanded so that any attributes of an exception class in a C function can be populated. The name, internal type (according to //src/include/abtypes.h), and the byte length must be specified:
//src/include/abexcpa.h
...
CX_ATTR (CX_..._attr1, CX_..., "ATTR1", TYPCSTRING, sizeofR(StrRef))
CX_ATTR (CX_..._attr2, CX_..., "ATTR2", TYPC, LEN_UC2RAW(30))
...
Finally, both exceptions and arguments must be registered in the file //src/krn/runt/abkmeth.sig. This is not forced but, during the syntax check, only registered exceptions are checked for their existence:
//src/krn/runt/abkmeth.sig
...
EXCEPTION(CX_...)
...
Raising Exceptions
A C function can raise an exception by calling the following macros consecutively:
EXCEPTION_CREATE(CX_..._bar);
EXCEPTION_SET_CSTRING(CX_..._attr1, value, valueLength);
EXCEPTION_SET_C (CX_..._attr2, value, valueLength);
EXCEPTION_RAISE();
Within the macros EXCEPTION_CREATE or EXCEPTION_RAISE, a long jump to Extri always takes place, which means that the C function that implements the kernel method is exited in a long jump and the ABAP runtime environment takes control. Therefore, the C function should release its temporary memory before raising an exception. If the exception is caught in ABAP using CATCH without the INTO addition, the long jump takes place in EXCEPTION_CREATE. If the exception is caught with the INTO addition (the exception object is used) or not at all, the long jump takes place in EXCEPTION_RAISE.
The exceptions are processed in the runtime environment, as if they were raised in ABAP and the same dynamic checks are executed.
Currently, the following macros, which can be expanded if necessary, are available for setting exception attributes. Strings, integer and C fields are supported. See the above sequence for use.
EXCEPTION_SET_CSTRING_UC
EXCEPTION_SET_C
Value with length specified
EXCEPTION_SET_C_UC
EXCEPTION_SET_INT
Value with null termination
Auxiliary Program for Kernel Methods
The ABAP program RSKMETH is used as a browser for the registration of kernel modules. This can be used to ascertain which C functions are registered for which kernel methods and which arguments/exceptions are registered for these functions. This is helpful when analyzing syntax errors, since kernel methods process information that only exists in the kernel modules.
Example
The following example is a simplified calculation class for floating decimal place numbers. The class has an instance attribute in which the last result of each calculation is stored. A method executes a division and is implemented as a kernel method. If the divisor is zero, the method raises a class-based exception.
Declaration Part of the Class in ABAP
CLASS cl_my_calculation DEFINITION ...
...
DATA last_result TYPE decfloat16.
...
METHODS div
IMPORTING p_dividend TYPE decfloat16 p_divisor TYPE decfloat16
RETURNING VALUE(p_result) TYPE decfloat16.
...
ENDCLASS.
Signature File //src/krn/runt/abkmeth.sig in the Kernel
...
KERNEL_METHOD(CL_MY_CALCULATION, DIV, xx_myDiv,4)
ARGUMENT_F(1, "P_DIVIDEND", TYPE, "F", READ)
ARGUMENT_F(2, "P_DIVISOR", TYPE, "F", READ)
ARGUMENT_F(3, "P_RESULT", TYPE, "F", WRITE)
ARGUMENT_F(4, "ME->LAST_RESULT",TYPE, "F", WRITE)
EXCEPTION("CX_MY_DIV_BY_ZERO")
...
C++ Source Code //src/krn/.../mycalc.cpp in the Kernel
#include "abkmeth.h"
...
externC void xx_myDiv( ARGUMENTS ){
const SAP_DOUBLE *const dividend = ARGUMENT_F_READ(1,"P_DIVIDEND");
const SAP_DOUBLE *const divisor = ARGUMENT_F_READ(2,"P_DIVISOR");
SAP_DOUBLE *result = ARGUMENT_F_WRITE(3,"P_RESULT");
SAP_DOUBLE *last_result = ARGUMENT_F_WRITE(4,"ME->LAST_RESULT");
if( 0 == *divisor )
{
EXCEPTION_CREATE(CX_MY_DIV_BY_ZERO);
EXCEPTION_RAISE();
}
*result = *dividend / *divisor;
*last_result = *result;
}
Implementation Part of the Class in ABAP
CLASS cl_my_calculation IMPLEMENTATION.
...
METHOD div BY KERNEL MODULE xx_myDiv.
ENDMETHOD.
...
ENDCLASS.
4. Constructors of Classes
Constructors are special methods that produce a defined initial state for objects and classes. The state of an object is determined by its instance attributes and static attributes. Contents can be assigned to attributes using the addition VALUE of the statement DATA. Constructors are necessary when the initial state of an object is to be defined dynamically.
Like normal methods, there are two types of constructor: instance constructors and static constructors.
Special rules apply to constructors in cases of inheritance. These rules are not described in this document, but can be found here.
◈ Instance Constructors
◈ Static Constructors
Instance Constructors
Each class has one instance constructor. This is a predefined instance method of the constructor class. To use the instance constructor, the constructor method must be declared in a visibility section of the class using the METHODS statement, and implemented in the implementation part. In global classes, the instance constructor can be declared in the public visibility section only, for technical reasons. In local classes, the visibility section in which the instance constructor can be declared must be more general or equal to the instantiability defined by the addition CREATE of the statement CLASS, where the most specialized area is recommended. Unless it is explicitly declared, the instance constructor is an implicit method, which inherits and accesses the interface from the instance constructor in the superclass.
Instance constructors are called once for each instance. They are called automatically, immediately after an instance is created using the statement CREATE OBJECT. It is not possible to call an instance constructor directly using the constructor( ... ); see super->constructor( ... ) in the inheritance.
An instance constructor can contain an interface with IMPORTING parameters and exceptions. The interface is defined using the same syntax as for regular methods in the statement METHODS. The fact that there are no exporting parameters shows that constructors only exist to define the state of an object and have no other function. The additions EXPORTING and EXCEPTIONS of the statement CREATE OBJECT are used to pass actual parameters and handle classical exceptions.
Static Constructors
Each class has a single static constructor. This is a predefined public static method of the constructor class. To use the static constructor, the static method class_constructor must be declared in the public section of the declaration part of the class using the statement CLASS-METHODS and implemented in the implementation part. The static constructor has no interface parameters and cannot raise exceptions. Unless declared explicitly, the static constructor is merely an empty method.
The static constructor is called once per class and internal session. The static constructor of a class class is called automatically before the class is accessed for the first time. The static constructor is always called immediately before the class is accessed, with one exception: If the class is accessed for the first time only to address a static attribute, the static constructor is executed at the beginning of the processing block (dialog module, event block, procedure) in which access takes place.
Notes
◈ The point at which the static constructor is called has not yet been finalized. It is only possible to ensure that it is called before the class is accessed for the first time. For this reason, static methods may be executed before the static constructor was ended.
◈ The execution order of static constructors is dependent on the program flow. Static constructors must be implemented so that they can be executed in any order.
Visibility of Instance Constructors
For technical reasons, the system declares the instance constructor of a class in a visibility section; it is therefore theoretically visible to the appropriate users. However, an instance constructor is only executed during the creation of an object of this class using CREATE OBJECT. Therefore the instance constructor is only visible to those consumers of a class that can also create objects of this class.
The additions CREATE PUBLIC|PROTECTED|PRIVATE of the statement CLASS determine whether every user, only the heirs, or just the class itself can create objects of the class. This means that these additions define the actual visibility of the instance constructor. Therefore the following applies:
◈ The instance constructor of a class defined using CREATE PUBLIC can be called by any consumer.
◈ The instance constructor of a class defined using CREATE PROTECTED can only be called by the class itself and its subclasses.
◈ The instance constructor of a class defined using CREATE PRIVATE can only be called by the class itself.
This has the following important consequence:
If a class was defined using CREATE PRIVATE, only the class itself can instantiate itself. Subclasses of this class cannot even instantiate themselves, because they would have to call the superclass constructor using CALL super->constructor (also see Inheritance and Instance Creation).
Constructors are special methods that produce a defined initial state for objects and classes. The state of an object is determined by its instance attributes and static attributes. Contents can be assigned to attributes using the addition VALUE of the statement DATA. Constructors are necessary when the initial state of an object is to be defined dynamically.
Like normal methods, there are two types of constructor: instance constructors and static constructors.
Special rules apply to constructors in cases of inheritance. These rules are not described in this document, but can be found here.
◈ Instance Constructors
◈ Static Constructors
Instance Constructors
Each class has one instance constructor. This is a predefined instance method of the constructor class. To use the instance constructor, the constructor method must be declared in a visibility section of the class using the METHODS statement, and implemented in the implementation part. In global classes, the instance constructor can be declared in the public visibility section only, for technical reasons. In local classes, the visibility section in which the instance constructor can be declared must be more general or equal to the instantiability defined by the addition CREATE of the statement CLASS, where the most specialized area is recommended. Unless it is explicitly declared, the instance constructor is an implicit method, which inherits and accesses the interface from the instance constructor in the superclass.
Instance constructors are called once for each instance. They are called automatically, immediately after an instance is created using the statement CREATE OBJECT. It is not possible to call an instance constructor directly using the constructor( ... ); see super->constructor( ... ) in the inheritance.
An instance constructor can contain an interface with IMPORTING parameters and exceptions. The interface is defined using the same syntax as for regular methods in the statement METHODS. The fact that there are no exporting parameters shows that constructors only exist to define the state of an object and have no other function. The additions EXPORTING and EXCEPTIONS of the statement CREATE OBJECT are used to pass actual parameters and handle classical exceptions.
Static Constructors
Each class has a single static constructor. This is a predefined public static method of the constructor class. To use the static constructor, the static method class_constructor must be declared in the public section of the declaration part of the class using the statement CLASS-METHODS and implemented in the implementation part. The static constructor has no interface parameters and cannot raise exceptions. Unless declared explicitly, the static constructor is merely an empty method.
The static constructor is called once per class and internal session. The static constructor of a class class is called automatically before the class is accessed for the first time. The static constructor is always called immediately before the class is accessed, with one exception: If the class is accessed for the first time only to address a static attribute, the static constructor is executed at the beginning of the processing block (dialog module, event block, procedure) in which access takes place.
Notes
◈ The point at which the static constructor is called has not yet been finalized. It is only possible to ensure that it is called before the class is accessed for the first time. For this reason, static methods may be executed before the static constructor was ended.
◈ The execution order of static constructors is dependent on the program flow. Static constructors must be implemented so that they can be executed in any order.
Visibility of Instance Constructors
For technical reasons, the system declares the instance constructor of a class in a visibility section; it is therefore theoretically visible to the appropriate users. However, an instance constructor is only executed during the creation of an object of this class using CREATE OBJECT. Therefore the instance constructor is only visible to those consumers of a class that can also create objects of this class.
The additions CREATE PUBLIC|PROTECTED|PRIVATE of the statement CLASS determine whether every user, only the heirs, or just the class itself can create objects of the class. This means that these additions define the actual visibility of the instance constructor. Therefore the following applies:
◈ The instance constructor of a class defined using CREATE PUBLIC can be called by any consumer.
◈ The instance constructor of a class defined using CREATE PROTECTED can only be called by the class itself and its subclasses.
◈ The instance constructor of a class defined using CREATE PRIVATE can only be called by the class itself.
This has the following important consequence:
If a class was defined using CREATE PRIVATE, only the class itself can instantiate itself. Subclasses of this class cannot even instantiate themselves, because they would have to call the superclass constructor using CALL super->constructor (also see Inheritance and Instance Creation).
5. Class Events
In ABAP Objects, events are declared as components of classes. SAP makes a distinction between instance events and static events. Triggers and handlers can be objects and classes, depending on whether they are instance events, static events, or event handlers.
Instance events
Instance events are declared using the statement EVENTS. They can only be triggered in instance methods.
Static events
Static events are declared using the statement CLASS-EVENTS. All methods (instance methods and static methods) can trigger static events. Static events, however, are the only events that can be triggered in static methods.
In ABAP Objects, events are declared as components of classes. SAP makes a distinction between instance events and static events. Triggers and handlers can be objects and classes, depending on whether they are instance events, static events, or event handlers.
Instance events
Instance events are declared using the statement EVENTS. They can only be triggered in instance methods.
Static events
Static events are declared using the statement CLASS-EVENTS. All methods (instance methods and static methods) can trigger static events. Static events, however, are the only events that can be triggered in static methods.
6. Data Types and Constants of Classes
Data Types
Standalone types
The TYPES statement can be used to define any number of self-defined ABAP data types within a class. Types are not instance-specific and only exist once for all the objects in the class.
In particular, it is possible to define data types in the public visibility section of global classes, which makes the use of type groups in this context obsolete.
Bound data types
Bound data types that occur as properties of instance attributes or static attributes are also static attributes of a class. After a LIKE addition, the class name can be used to access the properties of instance attributes (exceptions to this rule are the statements ASSIGN ... CASTING and SELECT-OPTIONS ... FOR). In addition, a reference variable can be used with an object component selector without the object having previously been created.
Constants
Constants are special static attributes, whose values are specified when they are declared and which cannot be changed later. Constants are declared using the statement CONSTANTS. Constants are not instance-specific and exist only once for all the objects in a class.
In particular, it is possible to define constants in the public visibility section of global classes, which makes the usage of type groups in this context obsolete.
Data Types
Standalone types
The TYPES statement can be used to define any number of self-defined ABAP data types within a class. Types are not instance-specific and only exist once for all the objects in the class.
In particular, it is possible to define data types in the public visibility section of global classes, which makes the use of type groups in this context obsolete.
Bound data types
Bound data types that occur as properties of instance attributes or static attributes are also static attributes of a class. After a LIKE addition, the class name can be used to access the properties of instance attributes (exceptions to this rule are the statements ASSIGN ... CASTING and SELECT-OPTIONS ... FOR). In addition, a reference variable can be used with an object component selector without the object having previously been created.
Constants
Constants are special static attributes, whose values are specified when they are declared and which cannot be changed later. Constants are declared using the statement CONSTANTS. Constants are not instance-specific and exist only once for all the objects in a class.
In particular, it is possible to define constants in the public visibility section of global classes, which makes the usage of type groups in this context obsolete.
◎ Inheritance
The concept of inheritance allows you to derive new classes from existing classes. To do this, you use the INHERITING FROM addition of the CLASS ... DEFINITION. The new class adopts or inherits all components of the existing class. The new class is called subclass, and the existing class is called superclass.
If you make no further declarations, a subclass contains exactly the components of the superclass. However, only the components of the public, protected, and package visibility section of the superclass are visible in the subclass. Although the private components of the superclass are also contained in the subclass, they are not visible. In a subclass, you can declare private components with the same name as the corresponding components of the superclass. Each class works with its private components. As long as a method inherited from the superclass is not redefined, it uses the private attributes of the superclass and not the possible subclass attributes of the same name.
If the superclass does not have a private visibility section, the subclass is an exact copy of the superclass. You can, however, add further components to the subclass. These components are used to specialize the subclass in relation to the superclass. If a subclass is then used as the superclass for a new class, you can then define a further level of specialization.
Each class can have several direct subclasses, but only one direct superclass. ABAP Objects applies the principle of single inheritance. If subclasses inherit from superclasses that are subclasses themselves, all classes involved represent an inheritance tree whose specialization increases the more deeper hierarchy levels are added. Specialization decreases the closer a level is located to the root node of the inheritance tree. The root node of all inheritance trees in ABAP Objects is the predefined empty class object. This class is the most generic class because it does not contain attributes or methods. When you define a new class, you must not explicitly specify this class as a superclass because it always exists implicitly. In the inheritance tree, two neighboring nodes are known as the direct superclass and subclass, while all preceding and succeeding nodes are collectively referred to as superclasses and subclasses. The declaration of the components of a subclass is distributed among all superclasses of the inheritance tree.
- - Redefining Methods
Each subclass contains the components of all classes that are located between this class and the root node in the inheritance tree. The visibility of a component is always the same and cannot be changed. However, it is possible to redefine the public and protected instance methods of all preceding superclasses using the addition REDEFINITION of the statement METHODS to modify them to the required level of specialization. The interface of a redefined method cannot be changed. The method is merely reimplemented under the same name. Constructors cannot be redefined; instead, special rules apply.
The method declaration remains with the superclass, and its previous implementation is also persisted there. The implementation of the redefinition is created again in the subclass and obscures the implementation of the superclass. A redefined method works with the private attributes of the subclass and not with possible private superclass attributes of the same name.
Each reference that points to a subclass object uses the redefined method, even if it was typed with reference to a superclass. In particular, this also applies to the self reference me. For example, if a superclass method m1 contains a call [me->]m2( ) or and if m2 is redefined in a subclass, the call of m1 in an instance of the superclass causes the original method m2 to be executed and the call of m1 in an instance of the subclass causes the redefined method m2 to be executed.
Within a redefined method, super->meth can be used to access the obscured method, for example to apply and supplement its functions.
- - Abstract and Final Methods and Classes
Abstract and final methods or classes can be defined using the additions ABSTRACT and FINAL of the statements METHODS and CLASS.
Abstract methods are declared in abstract classes and cannot be implemented in the same class. They must first be implemented in a subclass of the inheritance tree. Abstract classes cannot, therefore, be instantiated. A non-abstract method is a concrete method. With the exception of the instance constructor, concrete instance methods of a class can also call their abstract methods.
Final methods can no longer be redefined in subclasses. They cannot have any additional subclasses and close an inheritance tree definitively.
Notes
1. In classes that are both abstract and final, only the static components can be used. Although instance components can be declared, they cannot be used. Specifying ABSTRACT and FINAL together therefore is useful only for static classes.
2. Private methods cannot be redefined and can therefore not be abstract.
- - Inheritance and Polymorphism
Since a subclass contains all components of all superclasses along the inheritance tree and the interfaces of methods cannot be changed, a reference variable typed with reference to a superclass or to an interface implemented by a superclass may contain references to objects of all subclasses of this superclass. This means that the content of a reference variable typed with reference to a subclass can always be assigned to reference variables typed with reference to one of its superclasses or the interfaces of these superclasses (Up Cast). In particular, the target variable can always be typed with reference to the class object.
A static user can use a reference variable to address the components visible to it, which are contained in the superclass to which the reference variable refers. This means that it cannot address any specializations that have been added to the subclasses. With dynamic accesses, however, all components can be addressed.
When an instance method is redefined in one or more subclasses, different implementations of the method can be executed after a method call using the same reference variable, depending on where the class of the referenced object is located in the inheritance tree. The feature that different classes have the same interface and can therefore be addressed using reference variables of one type is called polymorphism.
- - Inheritance and Interfaces
Interfaces are standalone constructs in ABAP Objects that support polymorphism of classes. The polymorphism of interfaces is based on the fact that each class implementing an interface can implement the methods of that interface differently. To the outside world, all interface components look similar which is why interface reference variables can point to objects of all classes that implement the associated interface.
The interface concept exists independently of and in addition to the inheritance concept.The classes of an inheritance tree can implement any number of interfaces but each interface can be implemented only once in each inheritance tree. This ensures that each interface component comp has a unique name in the entire inheritance tree intf~icomp and that, starting with the class that implements it, it is contained in all subclasses. Interface reference variables that can point to a class of the inheritance tree can also point to all subclasses. Once implemented, interface methods are fully functioning components of a class and can be redefined in subclasses. In the case of interface methods defined as optional using DEFAULT (and without explicit implementation), the default behavior when called applies along a path of an inheritance tree until a redefinition with explicit implementation occurs.
- - Inheritance and Visibility
You cannot change the visibility area to which a component is assigned using inheritance. Component visibility affects inheritance as follows:
Public components
The public visibility area of a subclass consists of all its own public components plus the public components of all its superclasses. From outside the class, public components are visible without restrictions.
Protected components
The protected visibility area of a subclass consists of all its own protected components plus the protected components of all its superclasses. The protected section is visible only in the class itself and in all its subclasses. Viewed from outside, protected is the same as private.
Private components
The private visibility area of a subclass includes only the private components of this class. They are visible only in this class. The private components of superclasses cannot be used in subclasses. Only methods inherited from superclasses use (provided they have not been redefined) the private attributes of the superclass (even if the subclass has private attributes with the same name).
Example of protected components
Within a subnode in the inheritance tree, you can always access the protected components of superclasses. The classes involved, such as the static types of reference variables, must however be part of the inheritance tree.
In the following example, the reference variables lrefx and lref2 can see the protected components of cx in the context of the subclass c2. The static type of lref1 is c1 and is in another subnode of the inheritance tree. It cannot see any protected components of cx, in the context of c2. In a stricter model (C++ or Java), access in this example would only be possible using lref2. Access using lrefx would not be permitted, since it would involve classes (not subclasses) seeing protected components from outside. At present, ABAP extends the view of lrefx but only in a specific context. We intend, however, to introduce a stricter model and forbid access using lrefx. For this reason, you should not use this option; it causes a warning to be displayed in the extended program check.
CLASS cx DEFINITION.
PROTECTED SECTION.
METHODS mx.
ENDCLASS.
CLASS cx IMPLEMENTATION.
METHOD mx.
...
ENDMETHOD.
ENDCLASS.
CLASS c1 DEFINITION INHERITING FROM cx.
...
ENDCLASS.
CLASS c2 DEFINITION INHERITING FROM cx.
PUBLIC SECTION.
METHODS m2.
ENDCLASS.
CLASS c2 IMPLEMENTATION.
METHOD m2.
DATA: lrefx TYPE REF TO cx,
lref2 TYPE REF TO c2,
lref1 TYPE REF TO c1.
lrefx->mx( ). <--- Warning!!
lref2->mx( ).
lref1->mx( ). <--- Error!!
ENDMETHOD.
ENDCLASS.
- - Inheritance and the Component Namespace
A subclass contains all components of all its superclasses. Only the public and the protected components are visible. This is why all public and protected components of an inheritance tree are located in a single namespace and must have unique names. Private components, on the other hand, must only be named uniquely within a class.
When methods are redefined, the newly implemented method obscures the identically named method of the superclass. As soon as the method is redefined, it replaces the old method to ensure that the name remains unique. The pseudo reference super-> can be used in subclasses to access a method of the direct superclass which is hidden as a result of a redefinition.
- - Inheritance and Static Components
Static components, like all components, exist only once in each inheritance tree, and can be used from the level of the declaring class:
A subclass can access all non-private static components of its superclasses. The class in which the static component is declared is always the class that is addressed.
From outside, the class component selector can be used to access all visible static components. Each class can be specified in which the component exists (that is, the declaring class and each subclass). Regardless of the class name used in the class component selector, however, the class in which the component is declared is addressed.
The class in which the component is declared is always the class addressed, regardless of whether the static component is used internally or externally. This is important in the following cases:
Calls of the static constructors.
Static constructors are called the first time a class is addressed. If a static component is addressed that is declared in a superclass using the class name of a subclass, only the static constructor of the superclass is called.
Access to the static attributes
A subclass has access to the content of all non-private static attributes of all superclasses. Conversely, a superclass shares its public and protected static attributes with all of its subclasses. When inherited, therefore, static attributes are not just usable in a single class and can also be used to the subtree of the inheritance tree that consists of all subclasses of the defining class. Changes to the values are visible in all involved classes, regardless of the class used to address an attribute.
Registrations of event handlers.
If an event handler is declared for a static event of a subclass inherited from a superclass, it can react to this event only if it is raised by a method of the subclass or one of its subclasses. If the event is raised in a static method of a superclass, it is not handled, even if the method is called in a subclass or if the name of the subclass is specified.
Note
A static attribute of a class can be declared as a private attribute to prevent it from being used by all subclasses.
Example
Calls a static method of a superclass using the name of a subclass. Before the method is executed, the static constructor of the superclass is executed, but not the static constructor of the subclass. The method returns the value that is set in the superclass.
CLASS c1 DEFINITION.
PUBLIC SECTION.
CLASS-DATA a1 TYPE string.
CLASS-METHODS: class_constructor,
m1 RETURNING value(r1) LIKE a1.
ENDCLASS.
CLASS c1 IMPLEMENTATION.
METHOD class_constructor.
a1 = 'c1'.
ENDMETHOD.
METHOD m1.
r1 = a1.
ENDMETHOD.
ENDCLASS.
CLASS c2 DEFINITION INHERITING FROM c1.
PUBLIC SECTION.
CLASS-METHODS class_constructor.
ENDCLASS.
CLASS c2 IMPLEMENTATION.
METHOD class_constructor.
a1 = 'c2'.
ENDMETHOD.
ENDCLASS.
DATA v1 TYPE string.
START-OF-SELECTION.
v1 = c2=>m1( ).
Example
This example shows how a subclass is used to change a static attribute of a superclass, and how the change is visible in a subclass of a different path in the inheritance tree.
CLASS c1 DEFINITION.
PUBLIC SECTION.
CLASS-DATA a1 TYPE string.
ENDCLASS.
CLASS c11 DEFINITION INHERITING FROM c1.
...
ENDCLASS.
CLASS c12 DEFINITION INHERITING FROM c1.
...
ENDCLASS.
c11=>a1 = 'Hello Sister'.
MESSAGE c12=>a1 TYPE 'I'.
- - Inheritance and Constructors
There are special rules governing constructors in inheritance.
Instance Constructors
Each class has an instance constructor called constructor. This is an exception to the rule that states that component names along a path in an inheritance tree must be unique. The instance constructors of the various classes in an inheritance tree, however, are fully independent of one another.
◈ Instance constructors of superclasses cannot be redefined in subclasses.
◈ Instance constructors cannot be called explicitly using constructor( ... ).
This means that no naming conflicts can occur.
The instance constructor is called when an object is created using the command CREATE OBJECT or using the instance operator NEW. A subclass contains all of the visible attributes of its superclasses that can also be set by instance constructors, which means that the instance constructor of a subclass has to ensure that the instance constructors of all of its superclasses are also called. This requires that the instance constructor of each subclass contains a super->constructor call of the instance constructor of the direct superclass even if it is not explicitly declared. The only exception to this rule are direct subclasses of the root node OBJECT.
In superclasses without an explicitly defined instance constructor, the implicit instance constructor is called. This automatically ensures that the instance constructor of the immediate superclass is called.
When instance constructors are called, all of their non-optional input parameters must be filled as follows:
◈ Filling parameters in the case of CREATE OBJECT or NEW
Starting from the class of the new object, the first explicitly defined instance constructor in the associated path of the inheritance tree is respected. This is the instance constructor of the class itself or the first explicitly defined instance constructor of a superclass.
◈ Filling parameters in the case of super->constructor( ... )
Starting from the direct superclass, the first explicitly defined instance constructor in the associated path of the inheritance tree is respected.
The interface of the first explicitly defined instance constructor is filled in the same way as in a regular method. This means that:
◈ If no input parameters exist, no parameters are passed.
◈ Optional input parameters can be filled using EXPORTING.
◈ Non-optional input parameters must be filled using EXPORTING.
If there are no explicitly defined instance constructors in the path of the inheritance tree below the root class object, no parameters are passed.
In both CREATE OBJECT or NEW and super->constructor( ... ), the next available explicit instance constructor must be examined, and, if it has an interface, values passed to it. The same applies to exception handling for instance constructors. When working with inheritances, a precise knowledge of the entire inheritance tree is required. When a class at the bottom of the inheritance tree is instantiated, it may be necessary to pass parameters to the constructor of a class that is much nearer the root node.
The instance constructor of a subclass is divided into two parts by the call super->constructor( ... ) (demanded by the syntax). In the statements before the call, the constructor behaves like a static method, which means that the self reference me-> cannot be used and the constructor does not have access to the instance components of its class. me-> cannot be used until after the call and it is also possible to address instance components. The statements before the call are used to determine the actual parameters for the interface of the instance constructor of the superclass. Only static attributes or other visible data can be used for this.
When a subclass is instantiated, therefore, a nested call of the instance constructors from the subclass to the superclasses takes place. Here, however, the instance attributes can only be addressed in the lowest nesting level (which is the top superclass). When the constructors of the lower subclasses are revisited, their instance attributes can be addressed there successively too.
The methods of subclasses are not visible in constructors. If an instance constructor calls an instance method of the same class using the implicit self reference me, the method is called as implemented in the class of the instance constructor, and not in any redefined form that may occur in the subclass being instantiated. This is an exception to the rule that states that, when instance methods are called, the implementation is called in the class to whose instance the reference points.
Static Constructors
Every class has a static constructor called class_constructor. With respect to the namespace within an inheritance tree, the same applies to static constructors as to instance constructors.
When a subclass is addressed for the first time in program by creating an instance of the class or by a static component being addressed using the class component selector, the static constructor is called. However, before it can be called, the static constructors of all of its superclasses must already have been executed. A static constructor may only be called once per program. Therefore, when a subclass is first addressed, the next highest superclass is found whose static constructor has not yet been called. It calls the static constructor of that class, followed by the static constructors of all classes between that class and the subclass addressed.
- - Inheritance and Instantiation
When a subclass is instantiated, instantiate all the superclasses are instantiated at the same time. Here, the initialization of superclass attributes is ensured by the call of the superclass constructors, as described in Inheritance and Constructors.
For each individual class, the additions CREATE PUBLIC|PROTECTED|PRIVATE of the statement CLASS specify who can create an instance of the class or, in other words, can call its instance constructor.
This has the following consequences:
If a superclass is defined in a path of the inheritance tree using the addition CREATE PRIVATE, outside consumers cannot instantiate a subclass, and a subclass cannot even instantiate itself, because it has no access to the instance constructor of the superclass.
It would therefore also be useful to apply the addition FINAL to a class that was defined using the addition CREATE PRIVATE, to prevent a derivation of subclasses. Otherwise subclasses of such superclasses have the implicit addition CREATE NONE.
The only exception to this rule is if a superclass that can be privately instantiated offers its friendship to its subclasses. The direct route is rarely the case here because the superclass must know its subclasses in order for it to be possible. However, a superclass can also offer friendship to an interface which, in turn, can be implemented by its subclasses.
Conversely, objects of subclasses cannot be created in their superclass, if these are declared using CREATE PROTECTED or CREATE PRIVATE, unless they are friends of its subclasses.
Overview of All Cases
Superclass with no addition or CREATE PUBLIC
Whether a friend of the superclass or not, subclasses can have any CREATE addition. Without addition they inherit the attribute CREATE PUBLIC. The superclass instance constructor is visible to everyone. The subclass controls the visibility of its own instance constructor, independently of the superclass.
Superclass with addition CREATE PROTECTED.
Whether a friend of the superclass or not, subclasses can have any CREATE addition. Without addition they inherit the attribute CREATE PROTECTED. The superclass allows its subclasses unlimited instantiation and therefore also the publishing of its protected instance constructor.
Superclass with addition CREATE PRIVATE
Subclass is not a friend of the superclass
The subclass has the implicit addition CREATE NONE. Because nobody other than the superclass itself can call its instance constructor, the subclass cannot be instantiated. None of the CREATE additions is permitted, because this would always lead to the unauthorized publishing of the superclass constructor.
Subclass is a friend of the superclass
If the subclass has no addition, it inherits the attribute CREATE PRIVATE. However, all CREATE additions are permitted. As a friend, the subclass can publish the private constructor of the superclass in any form.
- - Inheritance and Events
Once declared in a superclass, an event is known in all subclasses of the inheritance tree in which it is visible, and can be raised in the methods there.
An event handler can be declared with reference to all classes of the inheritance tree in which the event is visible for the event handler. However, it can only handle events raised in classes that are more specific than or equal to the class for which it is declared. If the event is raised in a method of a superclass of the class for which an event handler is declared, it cannot handle it.
Note the latter especially when raising static events in static methods, since a static method is always executed in the class in which it was declared (also refer to Inheritance and Static Components).
Note
In the case of event handlers for events declared in interfaces, the above also applies to the class in which the interface is included.
◎ Interfaces
The components of a class are divided into visibility sections, and this forms the external point of contact between the class and its user. For example, the public components of a class define its public scope, since all of its attributes and method parameters can be addressed by all consumers. The protected components form an interface between the class and those classes that inherit from it (subclasses).
Interfaces are independent structures that enable the class-specific public points of contact to be enhanced by implementing them in classes. Different classes that implement the same interface can all be addressed in the same way. Alongside inheritance, interfaces provide one of the pillars of polymorphism, since they allow a single method within an interface to behave differently in different classes. Interface reference variables allow consumers to address different classes in the same manner. Interfaces can also be nested.
1. Defining Interfaces
2. Interface Components
3. Implementing Interfaces
4. Interface Reference Variables
5. Accessing Objects Using Interface References
6.Accessing the Static Components of Interfaces
1. Defining Interfaces
Like classes, interfaces can be defined either globally in the repository or locally in an ABAP program.
2. Interface Components
Exactly the same components can be defined in an interface as in a class.
3. Implementing Interfaces
Unlike classes, interfaces do not have instances. Instead, interfaces are implemented by classes. The INTERFACES statement in the declaration part of a class is used to implement interfaces in a class. This statement may only appear in the public section of the class, that is, after PUBLIC SECTION. Some interface components can be modified to meet the requirements of the class. For example, methods can be identified as abstract or final, or initial values can be assigned to attributes.
When an interface is implemented in a class, the components of the interface are added to the other components in the public section. A component comp of an interface intf can be addressed as though it were a member of the class under the name intf~comp. For use outside and inside the classes, ALIASES can be used to define alias names for these components.
The class must implement the methods of all interfaces implemented in it. The implementation part of the class must contain a method implementation for each non-abstract and non-optional interface method meth:
METHOD intf~meth.
...
ENDMETHOD.
Interface methods defined as optional using the addition DEFAULT do not need to be implemented explicitly and demonstrate default behavior when called.
Interfaces can be implemented by different classes. Each of these classes is enhanced using the same set of components. However, the methods of the interface can be implemented differently in each class.
Interfaces enable different classes to be used in a uniform way using interface reference variables (polymorphism). Interfaces that are implemented in different classes add the same components to the public interfaces of these classes. If a class does not have any class-specific public components, the interfaces define the entire public face of the class.
4. Interface Reference Variables
Object references are used in object reference variables to address objects. Instead of creating reference variables with reference to a class, they can also be created with reference to an interface. This kind of reference variable can contain references to objects of classes that implement the corresponding interface. A reference variable obj with reference to an interface intf is declared with the statement DATA obj TYPE REF TO intf. This reference variable allows programs access to precisely those components defined in the interface, that is, the components of an object that have been added to the class-specific components by implementing the interface.
5. Accessing Objects Using Interface References
To create an object of the class class, a reference variable cref must first be declared with reference to the class. If the class class implements an interface intf, the class reference variable cref can be assigned to the interface reference variable iref as follows:
iref = cref.
The reference in iref now points to the same object as the reference in cref.
It is also possible to create an object directly to which the interface reference variable points initially. In this case, the TYPE addition of the statement CREATE OBJECT must be used to specify a class that implements the interface.
CREATE OBJECT iref TYPE class.
If the interface intf contains an instance attribute attr and an instance method meth, the interface components can be addressed as follows:
Using the class reference variable (not recommended)
◈ Accessing an attribute attr: cref->intf~attr
◈ Calling a method meth: cref->intf~meth
Using the interface reference variable (recommended):
◈ Accessing an attribute attr: iref->attr
◈ Calling a method meth: iref->meth( )
6. Accessing the Static Components of Interfaces
As far as the static components of interfaces are concerned, the interface name can only be used to access constants.
◈ Accessing a constant const: intf=>const
For all other static components of an interface, only object references or the class class that implements the interface can be used.
◈ Accessing a static attribute attr:class=>intf~attr
◈ Calling a static method meth: class=>intf~meth( )
Nesting Interfaces
Interfaces can be nested. An interface can include one or more interfaces as components, which can contain interfaces themselves. An interface that includes another interface is called a compound interface. An interface nested within an interface is called a component interface. An interface that does not contain any compound interfaces is called an elementary interface.
All interface components of a compound interface have the same level. If a compound interface i3 contains another compound interface i2, its interface component i1 becomes interface component of i3. A compound interface includes each interface component exactly once. A component interface exists only once even if it is used again as a component of another component interface.
The statement INTERFACES is used for nesting interfaces within an interface definition:
INTERFACE i3.
INTERFACES: i1, i2 ...
ENDINTERFACE.
Here the interface i3 consists of its components and the interfaces i1 and i2. In the compound interface the components of the component interfaces are visible using the interface component selector (~). Within the above definition of i3, expressions such as i1~comp or i2~comp are possible. However, independent names can be defined using the ALIASES statement.
Using Alias Names
Within interface definitions, the statement ALIASES can be used to assign alias names to the components of component interfaces, and therefore make those nested to a depth greater than one level visible within the interface definition.
INTERFACE i2.
INTERFACES i1.
ALIASES alias21 FOR i1~comp1.
ENDINTERFACE.
INTERFACE i3.
INTERFACES i2.
ALIASES alias31 FOR i2~alias21.
ALIASES alias32 FOR i2~comp2.
ENDINTERFACE.
Accessing Interface Reference Variables
Reference variables typed with reference to a compound interface can be assigned reference variables typed with reference to one of the component interfaces ( up cast). The latter can be used to address the components of the component interfaces. The opposite case cannot be checked statically and must take place with the casting operator (?= or CAST) ( down cast).
INTERFACE i1.
DATA comp1.
ENDINTERFACE.
INTERFACE i2.
DATA comp2.
INTERFACES i1.
ENDINTERFACE.
INTERFACE i3.
INTERFACES i2.
ENDINTERFACE.
DATA: iref1 TYPE REF TO i1,
iref2 TYPE REF TO i2,
iref3 TYPE REF TO i3.
iref2 = iref3.
iref1 = iref2.
* recommended access:
... iref1->comp1 ...
... iref2->comp2 ...
* this access is not recommended:
... iref2->i1~comp1 ...
... iref3->i2~comp2 ...
Implementing Nested Interfaces in Classes
When a nested interface is implemented in a class, all associated interfaces are implemented in the class at the same level irrespective of their nesting hierarchy and the class must implement all methods only once.
INTERFACE i1.
DATA comp1.
METHODS meth1.
ENDINTERFACE.
INTERFACE i2.
DATA comp2.
INTERFACES i1.
ENDINTERFACE.
INTERFACE i3.
DATA comp3.
INTERFACES i2.
ENDINTERFACE.
CLASS class DEFINITION.
PUBLIC SECTION.
INTERFACES i3.
ENDCLASS.
CLASS class IMPLEMENTATION.
METHOD i1~meth.
...
ENDMETHOD.
ENDCLASS.
DATA cref TYPE REF TO class.
DATA iref1 TYPE REF TO i1.
DATA iref2 TYPE REF TO i2.
DATA iref3 TYPE REF TO i3.
iref1 = iref2 = iref3 = cref.
* recommended access:
... iref1->comp1 ...
... iref2->comp2 ...
... iref3->comp3 ...
* this access is not recommended:
... cref->i1~comp1 ...
... cref->i2~comp2 ...
... cref->i3~comp3 ...
... iref3->i1~comp1 ...
... iref3->i2~comp2 ...
... iref2->i1~comp1 ...
Assignments using up casts are always possible. Class reference variables for classes that implement a compound interface can be assigned to all interface references that are typed with reference to an associated interface component. In the class, the interface reference variables know only the components of their respective interfaces. The same applies for assignments between interface reference variables. It is possible to access components using the interface component selector, but this is not recommended. Compound expressions such as cref->i3~i2~comp2 or cref->i3~i2~i3~comp3 are not possible.
◎ Events
Events are generally characterized by occurring at a particular point in time. When an event is triggered, other actions can be executed as a consequence. Examples of when events can be triggered include changes in the status of an object, such as the cancellation of a posting or the generation of a new account (object). Other interested objects are informed of these situations by events.
In contrast to other object-oriented programming languages, the event concept in ABAP Objects is an integral component of the language itself. Using the statement EVENTS, objects can contain declared events as a part of their interface, and trigger them using RAISE EVENT. Using the addition FOR EVENT of the statement METHODS, other objects can also contain event handlers and therefore are able to react appropriately to an event. An object that triggers an event does not make any assumptions about which, and how many objects will handle the event, and if so, how this will be done. This means that the event concept represents a separation between the caller and the handler that must be clearly differentiated from a concept that uses callback routines, in which only one object reacts in a predefined manner. During a normal method call, a method can be called by any number of users, while the triggering of an event can lead to any number of event handlers being called. The link between the trigger and the handler is made at runtime. In a normal method call, the caller clearly defines which method he/she wants to call, and the corresponding method must exist. In events, the handler determines to which events it will react, and a handler does not have to be registered for every event.
An event handler in an object statically determines which events of which classes the object can handle. Before an object can react to relevant events, its event handlers must be dynamically registered for the events of other objects using the statement SET HANDLER. One object can be registered for the events of several other objects at the same time. This registration can be revoked at any time by users of the object or by the object itself. All registered event handlers are currently executed synchronously. This means that they are executed after the statement RAISE EVENT and before the next statement. This also applies for events that are triggered during the handling of other events.
If an object triggers an event during the execution of a method, each appropriate registered event handler method is called, and the triggering method can transfer parameters. If several event handlers are registered for one event, these are called in the sequence in which they were registered.
Event handlers can also be called directly. There can be two reasons for this: Either you want an event handler to handle an event without being registered, or to simulate the triggering of an event.
Events can have output parameters, which are defined in the same way as those of methods. An event handler can transfer these same output parameters as input parameters, whereby the transfer is always a value. In addition, there is always an implicit parameter called sender that contains a reference to the triggering object, via which the event handler gains access to this object.
◎ Friends - Friendship Between Classes
There is normally a strict division between external (PUBLIC) and internal (PROTECTED and PRIVATE) classes. A user can only access the public components of a class. This allows you to change the internal implementation of a class without invalidating its users.
In rare cases, however, classes have to work so closely together that they require access to each others' invisible components. The concept of friendship between classes has been developed so that these components do not need to be made available to all users at the same time.
Friends
A class can grant friendship to other classes and interfaces (and thus to all classes that implement this interface). To create this relationship, use the FRIENDS additions of the CLASS ... DEFINITION statement that includes all classes and interfaces to which you want to grant friendship. These friends are granted access to all components of the class offering the friendship, regardless of their visibility section or the addition READ-ONLY and can always create instances of this class regardless of the addition CREATE of the statement CLASS.
Friendship is unilateral
Friendship is a unilateral principle. A class that grants friendship is not automatically a friend of its friends. If the class that grants friendship wants to access the private or protected components of its friend, the latter must grant friendship explicitly.
Inheritance, Interfaces, and Friendship
Subclasses of friends and interfaces that are assigned a friend as a component interface also become friends. For this reason, you should be extremely careful when defining a friendship. The higher a friend is in the inheritance tree, the greater the number of subclasses that can access all of the components of the class granting friendship. A class that grants friendship to the root class object gains all of the ABAP Objects classes as friends and therefore has no privacy whatsoever. Conversely, it is relatively safe to grant friendship to a final class since this class alone is specified as a friend.
Friendship granted is not inherited, in contrast to the friend attribute. A friend of a superclass is, therefore, not automatically a friend of its subclasses.
The FRIENDS Additions
The statement CLASS ... DEFINITION has three FRIENDS additions:
◈ ... FRIENDS cif1 ... cifn
This addition can be specified when defining any local class of a program. Friendship can be granted to all classes or interfaces of the same program and to the classes and interfaces in the class library. Note, in particular, that the local classes of a class pool can grant friendship to the global class of that class pool.
◈ ... GLOBAL FRIENDS cif1 ... cifn
This addition can only be used with global classes and is created by the Class Builder during generation. Friendship can be granted to all other global classes and interfaces.
◈ ... LOCAL FRIENDS cif1 ... cifn
This addition is not specified when the class is declared, but instead defines its own statement. In a class pool, the global class can use this statement to grant friendship to the local classes and interfaces of its own class pool. While the Class Builder generates the CLASS statement for the actual class declaration, the statement
CLASS ... DEFINITION LOCAL FRIENDS cif1 ... cifn.
is entered directly in the include program for defining local classes and interfaces.
◎ Objects
Objects are instances of classes. There can be any number of objects or instances in a class. Each object has a unique identity and its own attributes.
By default, all objects have the same priority in the data area of an internal session. This means that objects can only be accessed from within an internal session.
For transaction-independent objects, shared objects are available, which can be accessed by all programs of an application server at the same time.
Object Services are available for handling persistent objects in the database. These link the attributes of objects with the content of database tables and can execute object-oriented transactions.
Creating Objects
Before an object can be created, an object reference variable is required that can point to the required class:
◈ Once a class reference variable obj is declared for a class class, an object of that class can be created using the statement CREATE OBJECT obj. This statement creates an instance of the class class and the reference variable obj contains a reference to this object.
◈ Once a class reference variable obj is declared for a superclass of the class class or an interface reference variable obj for an interface implemented by the class class, the TYPE class addition of the CREATE OBJECT obj statement can be used to create an instance of the class class.
The instance operator NEW enables objects to be created in general expression positions.
Access to Instance Components
A program can access the visible instance components of an object only through references in reference variables. For the syntax, see Accessing Components of Classes.
Lifetime of Objects
An object is kept alive for as long as it is used in the internal session (heap). The system will continue use the object provided that at least one heap reference points to the object, an instance attribute or part of the instance attribute or provided that at least one method of the object is registered as an event handler. Field symbols to which an instance attribute or part of an instance attribute is assigned still work in the same way as data references.
As soon as an object has no more references and none of its methods is registered as an event handler, it can be deleted by the Garbage Collector). This releases the identity of the object to be taken by a new object.
Note
Alongside these regular references, weak references represented by objects exist that do not keep an object alive.
1. Object References
Object references are used as pointer objects. Object references (the content of object reference variables) are the only way to access the components of objects in an ABAP program. References can be used to access attributes and methods, but not events.
Object Reference Variables
Object reference variables contain object references. An object reference variable oref is either initial or contains a reference to an existing object. In the latter case, the predicate expression oref IS BOUND is true. An object reference variable that points to an object contains the 'address' of the object. Objects and their components can only be addressed through object references.
Reference variables are data objects with a deep data type. A reference variable can be defined as the smallest indivisible unit of complex data objects such as structures and internal tables. When handling reference variables or complex data objects that contain reference variables, there are special features that apply to deep types.
Static Type of Object Reference Variables
Object reference variables can be created either as class reference variables or interface reference variables.
- Class Reference Variables
A reference variable with the static type of a class is called a class reference variable. Class reference variables are defined by the addition TYPE REF TO class of the TYPES statement or the DATA statement. In this case, class is a class known at the point of declaration.
A class reference variable cref enables the consumer to use the form cref->comp to access all of the visible components comp of the object to which the object reference points, which usually means all public components of the class.
- Interface Reference Variables
A reference variable with the static type of an interface is called an interface reference variable. Interface reference variables are defined by the addition TYPE REF TO intf of the TYPES statement or the DATA statement. In this case, intf is an interface known at the point of declaration.
An interface reference iref enables the consumer to use iref->icomp to access all of the visible interface components icomp of the object to which the reference points. Interface components are those components of an object that are declared by implementing the interface in the class.
As well as in declarations, the addition TYPE REF TO ... can be used in all other statements in which types can be specified, for example to specify the types of interface parameters in procedures.
- Special Object Reference Variables
Within a class there are two specific references, the self-reference me and the pseudo reference super.
◈ The self-reference me is used to address the components of an object explicitly. In the instance methods of a class, me is a predefined local reference variable with the same type as the class in which the instance method is implemented, which points to its own instance. It can be specified when addressing its own component but does not have to be. It can also be assigned to other reference variables or passed to methods.
◈ The pseudo reference super is used to call the obscured method in a redefined instance method in inheritances. The pseudo reference reference is not a genuine reference because an instance of a subclass cannot have an associated superclass instance, and hence cannot have a reference variable. The pseudo reference super is the syntax expression for a method call in a superclass.
Initializes Object Reference Variables
Like other variables, object reference variables are also initialized using the statement CLEAR. The initial value of an object reference variable is a reference that does not point to any object.
Assigning Object References Using Up Cast
Object references can be assigned between object reference variables. This means that the references in multiple reference variables can point to the same object (sharing). If assignments are made between reference variables, the dynamic type of the source variable must be compatible with the static type of the target variable. The dynamic type is the class of the object to which the reference in a reference variable points. The static type is the type (class or interface) with which the reference variable has been typed. The static type of the target variable must always be more general than the dynamic type of the source variable.
The syntax check in the program can only compare the static type of the source variable with the static type of the target variable. If reference variables are assigned using the assignment operator (=), the system performs this comparison and assignments can only be made that meet the above requirements for static types (up cast). The same applies when passing parameters to procedures. Assignments of this kind are always possible if the static type of the target variable can address the same number of components as the static type of the source variable or fewer components.
If cref1 and cref2 are class reference variables, and iref1 and iref2 are interface reference variables, the following assignments can be checked statically:
◈ cref1 = cref2
Both class reference variables must refer to the same class, or the class of cref1 is a superclass of the class of cref2. The class of cref1 can therefore always be object, because object is the superclass for all classes in ABAP Objects.
◈ iref1 = iref2
Both interface reference variables must refer to the same interface, or the interface of iref2 must be a nested interface that contains interface of iref1 as a component.
◈ iref1 = cref1
The class of the class reference variable cref1 or one of its superclasses must implement the interface of the interface reference variable iref1. The implementation can be performed directly or using a nested interface that contains the interface of iref1 as a component.
◈ cref1 = iref1
The class of cref1 must be object, that is, the reference variable cref1 must have the type REF TO object.
object is a predefined empty class and the root node for all inheritance trees in ABAP Objects. This class has no components and is the generic type of all object reference variables. Reference variables with the type object can be used as containers for passing references. They cannot be used for static access to objects. Dynamic access is possible.
Assigning Object References Using Down Cast
In all cases where a static type check is not possible, and in all cases where type checks are not performed until program runtime, an explicit down cast is necessary. The following make this possible:
◈ Assignments with the casting operator ?=. In this case, there is no static type check. Instead, the system checks at runtime whether the object reference in the source variable points to an object to which the object reference in the target variable may also point. The dynamic type of the source variable is compared with the static type of the target variable. If assignment is possible, the system assigns the reference, otherwise, it raises the handleable exception CX_SY_MOVE_CAST_ERROR.
◈ Constructor expressions using the casting operator CAST, which can be used in all operand positions. This has the same effect as an assignment, but can reduce the number of helper variables needed.
◈ The addition INTO of the statement WHEN TYPE in a case distinction with CASE TYPE OF. This combines a feasibility check for the down cast and the down cast itself.
The syntax requires a down cast to be used in all cases that are not listed above for static type checks.
For non-initial reference variables, the predicate expression IS INSTANCE OF or the case distinction CASE TYPE OF can be used to check whether a down cast can be applied to specific classes or interfaces.
Example
cref1 ?= iref1
Assigning an interface reference variable to a class reference variable. For the assignment to be successful, the object to which iref1 points must belong to the same class as the type of the class reference variable cref1 or to an appropriate subclass.
Object References as Actual Parameters
Object references can be passed as actual parameters to procedures (methods, function modules, and subroutines) by specifying object reference variables. As far as typed formal parameters are concerned, only actual parameters of exactly the same type can be passed if the formal parameter can be modified in the procedure. This applies also to EXPORTING and CHANGING parameters of function modules and methods, parameters in subroutines passed by reference and CHANGING parameters in subroutines passed by value.
Passing actual parameters to formal parameters that corresponds to an up cast, such as passing a class reference variable to a formal parameter which is typed with reference to an interface of the class or one of its superclasses, is not possible if the parameter can be changed in the procedure.
The reason is that a reference could be assigned to the actual parameter in the procedure which is incompatible with its static type, such as a reference to any other class that implements the same interface or a reference to a subclass in another path of the inheritance tree.
Assigning Object References to Field symbols
When object references are assigned to typed field symbols, the same applies as when passing a reference to typed formal parameters: The types must be identical. Otherwise, incompatibilities between dynamic and static types may occur. For example, if two class reference variables of different classes implementing the same interface one after the other are assigned to the same field symbol, an inconsistent state is produced.
2. Accessing Class Components
When accessing class components, there is a difference between access from inside and outside the same class. When a component is accessed from inside, that is within a method of the same class, the name of the component is sufficient. When a component is accessed from outside, the object for instance components and the class for static components must be specified with an object component selector or class component selector. There are static and dynamic variants.
For static access, object reference variables can only be used to access components that are known to the reference variable. These are the components that are available in the static type of the reference variable (class or interface). Class reference variables that are typed with reference to a superclass but point to subclasses know only the superclass components. Interface references know only interface components.
With dynamic access, the dynamic type is used to get the component for class reference variables. This is the type of the object to which the reference refers, and not the type used for typing the reference. For interface reference variables the static type is also used for dynamic access, that is, the type that was used to type the reference.
This means that reference variables that have been typed with reference to a superclass. They point to subclasses that can be used to dynamically access any component of the subclass for which dynamic access is possible. In particular, reference variables of the type REF TO OBJECT can be used to dynamically access components. However, it is not possible to use interface reference variables to access class-specific components dynamically; only the associated interface components can be accessed. It is not possible to access class-specific components using interface reference variables, because, when accessing with interface reference variables, the implicit use of the intf~ prefix is always required.
Static Access
The following syntax applies (oref is an object reference variable):
◈ Accessing an instance attribute attr: oref->attr
◈ Calling an instance method meth: oref->meth( ... )
In addition to reference variables, the class name can be used for accessing static components :
◈ Accessing a static attribute attr: class=>attr
◈ Calling a static method meth: class=>meth( ... )
In this context, it is important to note that the properties of instance methods behave like static components. Therefore, in a LIKE addition, the class component selector or reference variables can be used to refer to visible attributes of a class, without first creating an object.
In addition to specifying the name, accessing the components of a class is also possible using the self-reference me:
◈ Accessing attributes within the class attr: me->attr
◈ Calling a method within the same class meth: me->meth( ... )
Self-reference allows an object to pass a reference to itself to other objects. In addition, attributes within an object can be accessed in methods which are obscured by the local attributes of the method.
Within a redefined method of a subclass, the pseudo reference super can be used to access the obscured method in one of the superclasses:
◈ Calling an obscured method meth: super->meth( ... )
Within the instance constructor of a subclass, the pseudo reference super must be used to call the instance constructor of the direct superclass:
◈ Calling the constructor of the direct superclass:
super->constructor( ... )
As a specific method for accessing attributes, the attributes for key access to internal tables can be used if they contain reference variables.
Dynamic Access
Dynamic access to class components is only possible for attributes (dynamic access) and for method calls (dynamic invoke).
Accessing Attributes Dynamically
Dynamic access to attributes is possible using the dynamic ASSIGN to field symbols.
The following variants can be used (oref is an object reference variable):
Fully dynamic specification:
ASSIGN (f) TO <fs>.
Partly dynamic specification for instance attributes:
ASSIGN oref->(f) TO <fs>.
Partly dynamic specification for static attributes:
ASSIGN (f1)=>(f2) TO <fs>.
The contents of the fields f, f1 and f2 are interpreted as descriptors of attributes. In a completely dynamic case, f can, for example, have the content 'oref->attr'. In the case of the partly dynamic specification for instance attributes, f only describes the attribute (which itself can in turn describe another attribute). f1 and f2 can be class names and static attributes.
Dynamic Method Calls
The following syntax applies (oref is an object reference variable):
Calling an instance method meth:
CALL METHOD oref->(f)
Calling a static method meth:
CALL METHOD class=>(f)
CALL METHOD (c)=>meth
CALL METHOD (c)=>(f)
Calling a method within the same class meth:
CALL METHOD (f)
CALL METHOD me->(f)
f and c are fields containing the name of the method meth or class class.
In the case of dynamic method calls, the actual parameter can be passed dynamically to specific internal tables, similarly to calling function modules.
3. Object References in Internal Tables
If the row type of an internal table contains object reference variables in the form of the component comp, the attributes attr of the object (to which each reference of the row points) can be used as key values for reading, sorting, and modifying rows in tables. This is possible in the following statements or expressions:
◈ LOOP AT itab ... WHERE comp->attr ...
◈ READ TABLE itab ... WITH [TABLE] KEY comp->attr = ...
◈ ... itab [ KEY ... comp->attr = ... ] ...
◈ SORT itab BY comp->attr ...
◈ DELETE itab WHERE comp->attr ...
◈ MODIFY itab ... TRANSPORTING ... WHERE comp->attr ...
If a table contains unstructured rows with the type of an object reference variable, the attributes of the object to which a row points can be addressed using table_line->attr .
4. Weak References
An object in the system class CL_ABAP_WEAK_REFERENCE represents a weak reference to an object in a class. Unlike regular object references, a weak reference is ignored during execution of the garbage collector. This means that a weak reference does not prevent the referenced object from being deleted when the garbage collector is executed.
A weak reference to an existing object is created by passing an object reference to the instance constructor of CL_ABAP_WEAK_REFERENCE. The functional method GET can then be used to retrieve the reference afterwards. If the object was deleted in the meantime, the return value is initial.
Note
A different type of reference retains objects until the available memory becomes limited. The class CL_ABAP_SOFT_REFERENCE is available for these soft references, but this class is currently still implemented in the same way as class CL_ABAP_WEAK_REFERENCE.
◎ Statements in ABAP Objects
The statements in ABAP Objects can be classified as follows:
◈ Statements for defining classes and interfaces
The following statements are used to define classes and interfaces and their components. They can be used for local and global classes or interfaces.
◈ Statements for implementing methods
These statements implement the functions of classes in methods.
◈ Statements in class pools and interface pools
Alongside the statements for defining the global class, statements for local declarations and implementations can also be used in class pools. In interface pools, only one type group can be made public alongside the definition of the global interface.
A language cleanup has been carried out in ABAP Objects. The stricter ABAP syntax applies to all statements in ABAP Objects.
1. Statements for Defining Classes and Interfaces
The following statements are used to define classes and interfaces and their components. They can be used in any ABAP program where class and interface definitions are allowed.
Statements for Defining Classes
Defining the Declaration Part
CLASS ... DEFINITION ...
...
ENDCLASS ...
Defining the Implementation Part
CLASS ... IMPLEMENTATION ...
...
ENDCLASS ...
Statements for Defining Components of Classes
Statements in the Declaration Part
PUBLIC SECTION.
PROTECTED SECTION.
PRIVATE SECTION.
TYPES ...
INTERFACES ...
ALIASES ...
CONSTANTS ...
CLASS-DATA ...
DATA ...
CLASS-METHODS ...
METHODS ...
CLASS-EVENTS ...
EVENTS ...
Statements in the Implementation Part
METHOD ...
...
ENDMETHOD.
Statements for Defining Interfaces
Declaring the Interface
INTERFACE ...
...
ENDINTERFACE ...
Statements for Declaring Components of Interfaces
The same statements can be used to declare both components in interfaces as in the declaration part of classes.
Note
The components of classes or interfaces (their attributes, methods, and events) are declared in their declaration parts. TYPES can also be used to declare local data types. ALIASES can be used to declare alias names for the components of implemented interfaces. In a class, all declarations must belong to one of the four visibility sections introduced by the relevant statements.
The implementation part of a class can only contain method implementations between METHOD - ENDMETHOD blocks. In methods, only the statements for method implementations can be used.
No statements other than those specified above are necessary for defining classes or interfaces. Consequently, no other statements are allowed between CLASS - ENDCLASS or INTERFACE - ENDINTERFACE, except in methods.
The stricter syntax in ABAP Objects applies to all class and interface definitions.
2. Statements for Implementing Methods
The functions of classes are implemented in methods, between METHOD - ENDMETHOD.
The statements allowed in methods include all parts of the ABAP language allowed in all procedures. It must be noted, however, that all statements in methods are subject to the stricter syntax of ABAP Objects.
3. Statements in Class Pools and Interface Pools
Class pools and interface pools are the ABAP programs in the class library. They are defined using Class Builder tool in ABAP Workbench and are used as a repository for global classes and interfaces.
◈ A program of program type class pool is launched using the statement CLASS-POOL.
◈ A program of program type interface pool is launched using the statement INTERFACE-POOL.
These statements are generated by Class Builder.
Each class pool or interface pool can only contain a single global class or a single global interface. These classes or interfaces are declared using the following statements:
◈ CLASS ... PUBLIC. ... ENDCLASS.
◈ INTERFACE ... PUBLIC. ... ENDINTERFACE.
Class Builder uses the properties entered here to generate these statements.
Further Statements in Class Pools
As well as the declaration of the global class, a class pool can only contain the following statements:
◈ Declaration of local data types using the statement TYPES. These data types can be used by the global class in the private visibility section and in the implementation part.
◈ Declaration of local constants using the statement CONSTANTS. These data types can be used by the global class in the private visibility section and in the implementation part.
◈ Declaration of local interfaces using the statements INTERFACE ... ENDINTERFACE. These data types can be used by the global class in the private visibility section and in the implementation part.
◈ Declaration and implementation of local classes using the statements CLASS ... ENDCLASS.These data types can be used by the global class in the private visibility section and in the implementation part.
◈ Definition of macros using DEFINE ...END-OF-DEFINITION. These macros can be used by the global class in the implementation part.
Locally defined types, classes, and interfaces in class pools can be used in the following ways:
◈ Only the methods of the global class access the local declarations and implementations in the program. These provide auxiliary methods, for example, which should not be displayed in the interface of the global class. This is the most common scenario. Any changes made to local declarations in the program do not influence the interface of the global class.
◈ As well as the methods in the global class, declarations in the private visibility section of the class also reference local declarations in the program. This is a more unusual scenario, in which changes made to the local declarations influence the interface of the global class, and subclasses and friends of the global class are recompiled before the program is executed again.
Further Statements in Interface Pools
In addition to the declaration of the global interface, an interface pool cannot contain any of its own declarations or implementations.
Program Organization
Like any other ABAP program, class pools and interface pools consist of a global declaration part for declarations and an implementation part for implementations (or procedures).
◈ This means that the global declaration part of a class pool can contain the declarations of local data types, local interfaces, and local classes, as well as the actual declaration part of the global class. The implementation part of a class pool can contain the implementation parts of local classes, as well as the implementation part of the global class.
◈ The global declaration part of an interface pool can only contain the declaration of type groups and the declaration of the global interface. The implementation part of an interface pool is always empty.
Class Builder organizes the various declarations and implementations of a class pool or interface pool in include programs. The developer cannot usually view the names of these programs. A function in Class Builder enables the associated include programs to be opened and edited in ABAP Editor. Include programs exist for:
◈ Each visibility section in the declaration part of the global class
◈ Each implementation of a method of the global class
◈ Local declarations and implementations
◈ Test Classes for ABAP Unit
To edit the global class, Class Builder provides both editing functions for the individual include programs and a source code-based mode in which all the include programs can be displayed and edited as a single program.
Restrictions
Apart from the statements specified above, statements other than CLASS - ENDCLASS and INTERFACE - ENDINTERFACE are neither required in class pools and interface pools nor are they permitted. The stricter syntax of ABAP Objects applies to all statements permitted.
The following restrictions are particularly important:
◈ No processing blocks except methods
Neither event blocks such as START-OF-SELECTION, AT SELECTION-SCREEN, GET, or AT LINE-SELECTION nor dialog modules (defined by MODULE - ENDMODULE) are permitted. This means that runtime environment events cannot be processed. ABAP Objects has its own event concept. Neither function modules nor subroutines can be defined using FUNCTION - ENDFUNCTION or FORM - ENDFORM. The methods of a class pool can still call external function modules and subroutines, as well as methods.
◈ No interface work areas to other programs
The statements TABLES and NODES and the addition COMMON PART of the DATA statement are not possible. This means that class pools and interface pools do not support any global data areas across programs within a single internal session.
◈ No dedicated screens
Screen processing as implemented in other ABAP programs is not possible. No dynpros can be defined in a class pool or interface pool. If classic dynpros, including selection screens, are required, it is best to encapsulate them in function groups. It is preferable to use other suitable output media instead of classic lists. For table list output, the classes of SAP List Viewer (ALV), such as CL_SALV_TABLE, should be used. For simple text output, it is best to use browser control wrappers such as dynamic documents or text edit control wrappers.
◈ No processing of extracts
Extract data sets cannot be edited in global classes since the defining statement FIELD-GROUPS is not permitted in class or interface pools.
4. ABAP Objects - Keywords
The following list displays the keywords specially introduced for ABAP objects.
ALIASES | Declares an alias name |
CALL METHOD | Calls a method dynamically |
CLASS ... ENDCLASS | Defines a class |
CLASS-DATA | Declares a static attribute |
CLASS-EVENTS | Declares a static event |
CLASS-METHODS | Declares a static method |
CREATE OBJECT | Creates an object. |
EVENTS | Declares an instance event |
INTERFACE ... ENDINTERFACE | Defines an interface |
INTERFACES | Includes an interface |
METHOD ... ENDMETHOD | Defines a method |
METHODS | Declares an instance method |
PRIVATE SECTION | Introduces the package visibility section |
PROTECTED SECTION | Introduces the protected visibility section |
PUBLIC SECTION | Introduces the public visibility section |
RAISE EVENT | Triggers an event |
SET HANDLER | Registers an event |
5. Replacements for Obsolete Language Constructs in ABAP Objects
The ABAP language has been cleaned up in ABAP Objects. As part of this language clean-up, stricter syntax checks are performed for constructs that were previously allowed, or obsolete statements are no longer allowed at all. The stricter syntax checks usually produce syntax that is also recommended for use outside of ABAP Objects but where the old versions cannot be forbidden for compatibility reasons.
◎ Examples for ABAP Objects
1. ABAP Objects, Overview
This example demonstrates objects, object references, inheritance, interfaces, and events.
Source Code
REPORT demo_abap_objects.
*---------------------------------------------------------------------*
* Global Selection Screen
*---------------------------------------------------------------------*
SELECTION-SCREEN BEGIN OF SCREEN 100 AS WINDOW TITLE text-100.
PARAMETERS: button1 RADIOBUTTON GROUP grp,
button2 RADIOBUTTON GROUP grp,
button3 RADIOBUTTON GROUP grp,
button4 RADIOBUTTON GROUP grp.
SELECTION-SCREEN END OF SCREEN 100.
*---------------------------------------------------------------------*
* INTERFACE status
*---------------------------------------------------------------------*
* Interface definition *
*---------------------------------------------------------------------*
INTERFACE status.
METHODS write.
ENDINTERFACE.
*---------------------------------------------------------------------*
* CLASS vessel DEFINITION
*---------------------------------------------------------------------*
* Superclass definition *
*---------------------------------------------------------------------*
CLASS vessel DEFINITION.
PUBLIC SECTION.
METHODS: constructor,
drive
IMPORTING speed_up TYPE i,
get_id
RETURNING value(id) TYPE i.
PROTECTED SECTION.
DATA: speed TYPE i,
max_speed TYPE i VALUE 100.
PRIVATE SECTION.
CLASS-DATA object_count TYPE i.
DATA id TYPE i.
ENDCLASS.
*---------------------------------------------------------------------*
* CLASS vessel IMPLEMENTATION
*---------------------------------------------------------------------*
* Superclass implementation *
*---------------------------------------------------------------------*
CLASS vessel IMPLEMENTATION.
METHOD constructor.
object_count = object_count + 1.
id = object_count.
ENDMETHOD.
METHOD drive.
speed = speed + speed_up.
IF speed > max_speed.
speed = max_speed.
ENDIF.
ENDMETHOD.
METHOD get_id.
id = me->id.
ENDMETHOD.
ENDCLASS.
*---------------------------------------------------------------------*
* CLASS ship DEFINITION
*---------------------------------------------------------------------*
* Subclass definition *
*---------------------------------------------------------------------*
CLASS ship DEFINITION INHERITING FROM vessel.
PUBLIC SECTION.
INTERFACES status.
DATA name TYPE string READ-ONLY.
METHODS: constructor
IMPORTING name TYPE string,
drive
REDEFINITION.
EVENTS emergency_call.
ENDCLASS.
*---------------------------------------------------------------------*
* CLASS ship IMPLEMENTATION
*---------------------------------------------------------------------*
* Subclass implementation *
*---------------------------------------------------------------------*
CLASS ship IMPLEMENTATION.
METHOD constructor.
super->constructor( ).
max_speed = 30.
me->name = name.
ENDMETHOD.
METHOD status~write.
DATA id TYPE c LENGTH 1.
id = me->get_id( ).
WRITE: / name, 'is vessel', id,
'and has speed', speed.
ENDMETHOD.
METHOD drive.
speed = speed + speed_up.
IF speed > max_speed.
max_speed = 0.
speed = 0.
RAISE EVENT emergency_call.
ENDIF.
ENDMETHOD.
ENDCLASS.
*---------------------------------------------------------------------*
* CLASS coast_guard DEFINITION
*---------------------------------------------------------------------*
* Event handler definition *
*---------------------------------------------------------------------*
CLASS coast_guard DEFINITION.
PUBLIC SECTION.
INTERFACES status.
METHODS receive
FOR EVENT emergency_call OF ship
IMPORTING sender.
ALIASES write FOR status~write.
PRIVATE SECTION.
DATA caller TYPE string.
ENDCLASS.
*---------------------------------------------------------------------*
* CLASS coast_guard IMPLEMENTATION
*---------------------------------------------------------------------*
* Event handler implementation *
*---------------------------------------------------------------------*
CLASS coast_guard IMPLEMENTATION.
METHOD status~write.
IF caller IS INITIAL.
WRITE: / 'Coast guard received no call'.
ELSE.
WRITE: / 'Coast guard received a call from', caller.
ENDIF.
ENDMETHOD.
METHOD receive.
caller = sender->name.
write( ).
ENDMETHOD.
ENDCLASS.
*---------------------------------------------------------------------*
* CLASS main DEFINITION
*---------------------------------------------------------------------*
* Main class definition *
*---------------------------------------------------------------------*
CLASS main DEFINITION.
PUBLIC SECTION.
CLASS-METHODS: start,
objects,
inheritance,
interfaces,
events.
ENDCLASS.
*---------------------------------------------------------------------*
* CLASS main IMPLEMENTATION
*---------------------------------------------------------------------*
* Main class implementation *
*---------------------------------------------------------------------*
CLASS main IMPLEMENTATION.
METHOD start.
CALL SELECTION-SCREEN 100 STARTING AT 10 3
ENDING AT 42 7.
IF sy-subrc NE 0.
EXIT.
ELSEIF button1 = 'X'.
objects( ).
ELSEIF button2 = 'X'.
inheritance( ).
ELSEIF button3 = 'X'.
interfaces( ).
ELSEIF button4 = 'X'.
events( ).
ENDIF.
ENDMETHOD.
METHOD objects.
DATA: vessel1 TYPE REF TO vessel,
vessel2 TYPE REF TO vessel.
DATA: vessel_id TYPE i.
CREATE OBJECT: vessel1 TYPE vessel,
vessel2 TYPE vessel.
vessel1->drive( 50 ).
vessel2->drive( 80 ).
vessel_id = vessel1->get_id( ).
WRITE: / 'Vessel ID is', vessel_id.
vessel_id = vessel2->get_id( ).
WRITE: / 'Vessel ID is', vessel_id.
ENDMETHOD.
METHOD inheritance.
DATA: vessel TYPE REF TO vessel,
ship TYPE REF TO ship.
CREATE OBJECT ship TYPE ship
EXPORTING
name = 'Titanic'.
ship->drive( 20 ).
vessel = ship.
vessel->drive( 10 ).
ship->status~write( ).
ENDMETHOD.
METHOD interfaces.
DATA: status_tab TYPE TABLE OF REF TO status,
status TYPE REF TO status.
status_tab = VALUE #( ( NEW ship( name = 'Titanic' ) )
( NEW coast_guard( ) ) ).
LOOP AT status_tab INTO status.
status->write( ).
ENDLOOP.
ENDMETHOD.
METHOD events.
DATA: ship TYPE REF TO ship,
station TYPE REF TO coast_guard.
CREATE OBJECT: ship EXPORTING name = 'Titanic',
station.
SET HANDLER station->receive FOR ship.
DO 5 TIMES.
ship->drive( 10 ).
ENDDO.
ENDMETHOD.
ENDCLASS.
*---------------------------------------------------------------------*
* System event START-OF-SELECTION
*---------------------------------------------------------------------*
* Triggered by the ABAP runtime environment automatically *
*---------------------------------------------------------------------*
START-OF-SELECTION.
main=>start( ).
*---------------------------------------------------------------------*
Description
The program contains a class main with a method start which is called at program start and demonstrates the use of ABAP objects using the example of classes of water vehicles.
2. ABAP Objects, Classes
This example demonstrates a class for counters.
Source Code
REPORT demo_class_counter .
CLASS counter DEFINITION.
PUBLIC SECTION.
METHODS: set
IMPORTING value(set_value) TYPE i,
increment,
get
EXPORTING value(get_value) TYPE i.
PRIVATE SECTION.
DATA count TYPE i.
ENDCLASS.
CLASS counter IMPLEMENTATION.
METHOD set.
count = set_value.
ENDMETHOD.
METHOD increment.
ADD 1 TO count.
ENDMETHOD.
METHOD get.
get_value = count.
ENDMETHOD.
ENDCLASS.
DATA number TYPE i VALUE 5.
DATA cnt TYPE REF TO counter.
START-OF-SELECTION.
CREATE OBJECT cnt.
cnt->set( number ).
DO 3 TIMES.
cnt->increment( ).
ENDDO.
cnt->get( IMPORTING get_value = number ).
cl_demo_output=>display( number ).
Description
The counter class contains three public methods set, increment and get, which work with the private integer field count. Two of the methods have input and output parameters with which they define the data interface of the class. The field count is not visible externally.
3. ABAP Objects, Inheritance
This example demonstrates the specialization of a counter using inheritance.
Source Code
REPORT demo_inheritance.
CLASS counter DEFINITION.
PUBLIC SECTION.
METHODS: set
IMPORTING value(set_value) TYPE i,
increment,
get
EXPORTING value(get_value) TYPE i.
PROTECTED SECTION.
DATA count TYPE i.
ENDCLASS.
CLASS counter IMPLEMENTATION.
METHOD set.
count = set_value.
ENDMETHOD.
METHOD increment.
ADD 1 TO count.
ENDMETHOD.
METHOD get.
get_value = count.
ENDMETHOD.
ENDCLASS.
CLASS counter_ten DEFINITION INHERITING FROM counter.
PUBLIC SECTION.
METHODS increment REDEFINITION.
DATA count_ten TYPE c LENGTH 1.
ENDCLASS.
CLASS counter_ten IMPLEMENTATION.
METHOD increment.
DATA modulo TYPE i.
super->increment( ).
modulo = count MOD 10.
IF modulo = 0.
count_ten = count_ten + 1.
cl_demo_output=>write_text( |{ count } - { count_ten }| ).
ELSE.
cl_demo_output=>write_text( |{ count }| ).
ENDIF.
ENDMETHOD.
ENDCLASS.
DATA: count TYPE REF TO counter,
number TYPE i VALUE 5.
START-OF-SELECTION.
CREATE OBJECT count TYPE counter_ten.
count->set( number ).
DO 20 TIMES.
count->increment( ).
ENDDO.
cl_demo_output=>display( ).
Description
The counter_ten class is derived from counter and redefines the increment method. In counter, the visibility of the attribute count must be changed from PRIVATE to PROTECTED. In the redefined method, the nested method with the pseudo reference super-> is called. The redefined method specializes the inherited method.
An object of the subclass is created, to which a reference variable of the superclass type points. During the execution of the increment method, the redefined method of the subclass is executed using the superclass reference.
4. ABAP Objects, Interfaces
This example demonstrates the use of interfaces.
Source Code
REPORT demo_interface.
INTERFACE status.
METHODS write.
ENDINTERFACE.
CLASS counter DEFINITION.
PUBLIC SECTION.
INTERFACES status.
METHODS increment.
PRIVATE SECTION.
DATA count TYPE i.
ENDCLASS.
CLASS counter IMPLEMENTATION.
METHOD status~write.
cl_demo_output=>write_text( |Count in counter is { count }| ).
ENDMETHOD.
METHOD increment.
ADD 1 TO count.
ENDMETHOD.
ENDCLASS.
CLASS bicycle DEFINITION.
PUBLIC SECTION.
INTERFACES status.
METHODS drive.
PRIVATE SECTION.
DATA speed TYPE i.
ENDCLASS.
CLASS bicycle IMPLEMENTATION.
METHOD status~write.
cl_demo_output=>write_text( |Speed of bicycle is { speed }| ).
ENDMETHOD.
METHOD drive.
ADD 10 TO speed.
ENDMETHOD.
ENDCLASS.
DATA: count TYPE REF TO counter,
bike TYPE REF TO bicycle,
status TYPE REF TO status,
status_tab TYPE TABLE OF REF TO status.
START-OF-SELECTION.
CREATE OBJECT: count, bike.
DO 5 TIMES.
count->increment( ).
bike->drive( ).
ENDDO.
APPEND: count TO status_tab,
bike TO status_tab.
LOOP AT status_tab INTO status.
status->write( ).
ENDLOOP.
cl_demo_output=>display( ).
Description
This example shows a status interface for outputting the attributes of an object and its implementation in two different classes.
The status interface contains a write method. The counter and bicycle classes implement the interface in the public area. Both classes must implement the interface method in the implementation part corresponding to the required semantics.
First, two class reference variables are declared, count and bike, for the classes counter and bicycle. An interface reference variable status and an internal table status_tab with a suitable row type for the interface reference variable, are created for the status interface. All the reference variables begin with initial values.
Using the CREATE OBJECT statement, an object is created for each class, to which the references in count and bike point. Using the class reference variable, the increment and drive methods are called in the respective objects.
Through the addition of the class reference variables to the interface reference table, the rows in status_tab also point to the two objects. Using the interface references, it is possible to call the interface method write in the objects, but not the class methods increment or drive.
5. ABAP Objects, Events
The example demonstrates triggering and handling events.
Source Code
REPORT demo_abap_objects_events NO STANDARD PAGE HEADING.
************************************************************************
* Declarations
************************************************************************
INTERFACE i_vehicle.
DATA max_speed TYPE i.
EVENTS: speed_change EXPORTING value(new_speed) TYPE i.
METHODS: drive,
stop.
ENDINTERFACE.
CLASS c_ship DEFINITION.
PUBLIC SECTION.
METHODS constructor.
INTERFACES i_vehicle.
PRIVATE SECTION.
ALIASES max FOR i_vehicle~max_speed.
DATA ship_speed TYPE i.
ENDCLASS.
CLASS c_truck DEFINITION.
PUBLIC SECTION.
METHODS constructor.
INTERFACES i_vehicle.
PRIVATE SECTION.
ALIASES max FOR i_vehicle~max_speed.
DATA truck_speed TYPE i.
ENDCLASS.
CLASS status DEFINITION.
PUBLIC SECTION.
CLASS-EVENTS button_clicked EXPORTING value(fcode) TYPE sy-ucomm.
CLASS-METHODS: class_constructor,
user_action.
ENDCLASS.
CLASS c_list DEFINITION.
PUBLIC SECTION.
METHODS: fcode_handler FOR EVENT button_clicked OF status
IMPORTING fcode,
list_change FOR EVENT speed_change OF i_vehicle
IMPORTING new_speed,
list_output.
PRIVATE SECTION.
DATA: id TYPE i,
ref_ship TYPE REF TO c_ship,
ref_truck TYPE REF TO c_truck,
BEGIN OF line,
id TYPE i,
flag(1) TYPE c,
iref TYPE REF TO i_vehicle,
speed TYPE i,
END OF line,
list LIKE SORTED TABLE OF line WITH UNIQUE KEY id.
ENDCLASS.
DATA list TYPE REF TO c_list.
************************************************************************
* Implementations
************************************************************************
CLASS c_ship IMPLEMENTATION.
METHOD constructor.
max = 30.
ENDMETHOD.
METHOD i_vehicle~drive.
CHECK ship_speed < max.
ship_speed = ship_speed + 10.
RAISE EVENT i_vehicle~speed_change
EXPORTING new_speed = ship_speed.
ENDMETHOD.
METHOD i_vehicle~stop.
CHECK ship_speed > 0.
ship_speed = 0.
RAISE EVENT i_vehicle~speed_change
EXPORTING new_speed = ship_speed.
ENDMETHOD.
ENDCLASS.
CLASS c_truck IMPLEMENTATION.
METHOD constructor.
max = 150.
ENDMETHOD.
METHOD i_vehicle~drive.
CHECK truck_speed < max.
truck_speed = truck_speed + 50.
RAISE EVENT i_vehicle~speed_change
EXPORTING new_speed = truck_speed.
ENDMETHOD.
METHOD i_vehicle~stop.
CHECK truck_speed > 0.
truck_speed = 0.
RAISE EVENT i_vehicle~speed_change
EXPORTING new_speed = truck_speed.
ENDMETHOD.
ENDCLASS.
CLASS status IMPLEMENTATION.
METHOD class_constructor.
SET PF-STATUS 'VEHICLE'.
WRITE 'Click a button!'.
ENDMETHOD.
METHOD user_action.
RAISE EVENT button_clicked EXPORTING fcode = sy-ucomm.
ENDMETHOD.
ENDCLASS.
CLASS c_list IMPLEMENTATION.
METHOD fcode_handler.
CLEAR line.
CASE fcode.
WHEN 'CREA_SHIP'.
id = id + 1.
CREATE OBJECT ref_ship.
line-id = id.
line-flag = 'C'.
line-iref = ref_ship.
APPEND line TO list.
WHEN 'CREA_TRUCK'.
id = id + 1.
CREATE OBJECT ref_truck.
line-id = id.
line-flag = 'T'.
line-iref = ref_truck.
APPEND line TO list.
WHEN 'DRIVE'.
CHECK sy-lilli > 0.
line = list[ sy-lilli ].
line-iref->drive( ).
WHEN 'STOP'.
LOOP AT list INTO line.
line-iref->stop( ).
ENDLOOP.
WHEN 'CANCEL'.
LEAVE PROGRAM.
ENDCASE.
list_output( ).
ENDMETHOD.
METHOD list_change.
line-speed = new_speed.
MODIFY TABLE list FROM line.
ENDMETHOD.
METHOD list_output.
sy-lsind = 0.
SET TITLEBAR 'TIT'.
LOOP AT list INTO line.
IF line-flag = 'C'.
WRITE / icon_ws_ship AS ICON.
ELSEIF line-flag = 'T'.
WRITE / icon_ws_truck AS ICON .
ENDIF.
WRITE: 'Speed = ', line-speed.
ENDLOOP.
ENDMETHOD.
ENDCLASS.
************************************************************************
* Program events
************************************************************************
START-OF-SELECTION.
CREATE OBJECT list.
SET HANDLER: list->fcode_handler,
list->list_change FOR ALL INSTANCES.
AT USER-COMMAND.
status=>user_action( ).
Description
The user actions on a classic list trigger events in ABAP objects. The list and its data are implemented in the class c_list. There is a class status for processing user actions. It triggers an event button_clicked in the AT USER-COMMAND event. The event is handled in the class c_list. The class c_list contains an object of the class c_ship or c_truck for each line of the list. Both of these classes implement the interface i_vehicle. Whenever the speed of one of these objects changes, the event speed_change is triggered. The class c_list reacts to this and updates the list.
6. ABAP Objects, OO Transaction
This example demonstrates the linking of a transaction code with the method of a local class.
Source Code
*&---------------------------------------------------------------------*
*& Subroutine pool DEMO_OO_TRANSACTION *
*& *
*&---------------------------------------------------------------------*
PROGRAM demo_oo_transaction.
*
CLASS demo_class DEFINITION.
PUBLIC SECTION.
METHODS instance_method.
ENDCLASS.
*
CLASS demo_class IMPLEMENTATION.
METHOD instance_method.
cl_demo_output=>display( 'Instance method in local class' ).
ENDMETHOD.
ENDCLASS.
Description
The program DEMO_OO_TRANSACTION is a subroutine pool that does not contain any subroutines. Instead, the program contains the definition of the local class demo_class, with which the transaction code DEMO_OO_METHOD is linked. When the transaction is called, the program is loaded, one instance of the class is created, and the method is called.
1.2.2 CLASS
Syntax Forms
Declaration Part of a Class
1. CLASS class DEFINITION [class_options].
[PUBLIC SECTION.
[components]]
[PROTECTED SECTION.
[components]]
[PRIVATE SECTION.
[components]]
ENDCLASS.
Implementation Part of a Class
2. CLASS class IMPLEMENTATION.
...
METHOD ...
...
ENDMETHOD.
...
ENDCLASS.
Publication of Classes
3. CLASS class DEFINITION DEFERRED [PUBLIC].
Local Friends of Global Classes
4. CLASS class DEFINITION
LOCAL FRIENDS class1 class2 ...
intf1 intf2 ...
Effect
The statement CLASS defines a class class, publishes it, or specifies properties.
◉ The complete definition of a class consists of a declaration part and an implementation part, which are both introduced by CLASS and ended by ENDCLASS. In the declaration part, the properties of the class are specified and its components are declared. In the implementation part, the methods of the class are implemented.
◉ The variants of CLASS without ENDCLASS are used for the publication of classes in a program and the declaration of local friends of a global class.
The statements CLASS and associated statements ENDCLASS can be specified only in the global context of a program. CLASS and ENDCLASS cannot be specified within classes, procedures, and processing blocks implemented internally as a procedure (event blocks for GET and AT SELECTION-SCREEN). This applies in particular to the variants of CLASS specified here, which is not closed using ENDCLASS.
Notes
◉ The declaration part of a class, and the variants of CLASS not closed using ENDCLASS are handled like other declaration statements (DATA, TYPE, ...). In a processing block without a local context, they are handled like global program declarations and do not end the processing block.
◉ Overall, the implementation part of a class works like a separate processing block and closes any other processing blocks.
◉ The obsolete variant CLASS ... DEFINITION LOAD was formerly used to load classes explicitly.
1. CLASS - DEFINITION
Syntax
CLASS class DEFINITION [class_options].
[PUBLIC SECTION.
[components]]
[PROTECTED SECTION.
[components]]
[PRIVATE SECTION.
[components]]
ENDCLASS.
Effect
The statement block CLASS class DEFINITION - ENDCLASS declares a class named class. Naming conventions apply to the name class. components of the class are declared between CLASS and ENDCLASS. Each component must be included in a visibility section after one of the statements PUBLIC SECTION, PROTECTED SECTION, or PRIVATE SECTION. These statements must be specified in the order above. The class does not need to include all the SECTION statements.
The class options additions of the statement CLASS can be used to publish a class globally in the class library, define an inheritance relationship, make the class abstract or final, control where the class can be instantiated, and offer friendship to other classes or interfaces.
Notes
◈ The class is the smallest encapsulation unit in ABAP Objects. A method can therefore use all components of all instances of the same class apart from the components of its own instance. An exception to this rule are subclasses that cannot access the private components of superclasses, if they are not their friends.
◈ The declaration part of a class can only be specified in the context described under CLASS.
➥ CLASS - class_options
Syntax
... [PUBLIC]
[INHERITING FROM superclass]
[ABSTRACT]
[FINAL]
[CREATE {PUBLIC|PROTECTED|PRIVATE}]
[SHARED MEMORY ENABLED]
[ FOR TESTING]
[[GLOBAL] FRIENDS class1 class2 ...
intf1 intf2 ...].
Additions
1. ... PUBLIC
2. ... INHERITING FROM superclass
3. ... ABSTRACT
4. ... FINAL
5. ... CREATE {PUBLIC|PROTECTED|PRIVATE}
6. ... SHARED MEMORY ENABLED
7. ... [GLOBAL] FRIENDS class1 class2 ... intf1 intf2 ...
Effect
Defines the properties of a class. A test class for ABAP unit is created with addition FOR TESTING.
Addition 1
... PUBLIC
Effect
The addition PUBLIC specifies that the class class is a global class in the class library. The addition PUBLIC can only be applied to one class in a class pool. This addition is created by Class Builder when a global class is created. Any class that does not have the addition PUBLIC applied to it is a local class in its program.
Notes
◈ References to public data types can only be made in the public visibility section of a global class.
◈ Data types and constants declared in the public visibility section of global classes using the statements TYPES and CONSTANTS replace declarations in type groups.
Addition 2
... INHERITING FROM superclass
Effect
The addition INHERITING FROM specifies that the class class is derived from the superclass superclass and as such is a direct subclass of it. The superclass superclass can be any non-final class that is visible at this point.
Each class can only have one superclass, but multiple direct subclasses (single inheritance). Every class without the addition INHERITING FROM inherits implicitly from the predefined empty, abstract class object. All classes in ABAP Objects form an inheritance tree, in which there is a unique path from each class to the root object object.
The class class inherits all components of superclass, without changing their visibility sections. Only the components of public and protected visibility sections are visible in the subclass. The properties of the inherited components cannot be changed. In the subclass, additional components can be declared and inherited methods redefined – that is, they can be reimplemented without the interface being modified.
Note
The public and protected components of all classes in a path in the inheritance tree are in the same namespace. New components in a subclass cannot have the same name as a public or protected component that has been inherited from the superclasses.
Addition 3
... ABSTRACT
Effect
The addition ABSTRACT defines an abstract class class. No instances can be created from an abstract class. To use the instance components of an abstract class, a concrete subclass of the class must be instantiated.
Addition 4
... FINAL
Effect
The addition FINAL defines a final class class. No subclasses can be derived from a final class. All methods of a final class are implicitly final and cannot be declared explicitly as final.
Note
In classes that are both abstract and final, only the static components can be used. Although instance components can be declared, they cannot be used. Specifying ABSTRACT and FINAL together therefore is useful only for static classes.
Example
In this example, an abstract class c1 and a final class c2 are defined, such that c2 inherits from c1. c1 is an implicit subclass of the empty class object. In c2, m1 can be accessed but not a1.
CLASS c1 DEFINITION ABSTRACT.
PROTECTED SECTION.
METHODS m1.
PRIVATE SECTION.
DATA a1 TYPE string VALUE `Attribute A1 of class C1`.
ENDCLASS.
CLASS c2 DEFINITION INHERITING FROM c1 FINAL.
PUBLIC SECTION.
METHODS m2.
ENDCLASS.
CLASS c1 IMPLEMENTATION.
METHOD m1.
cl_demo_output=>display_text( a1 ).
ENDMETHOD.
ENDCLASS.
CLASS c2 IMPLEMENTATION.
METHOD m2.
m1( ).
ENDMETHOD.
ENDCLASS.
DATA oref TYPE REF TO c2.
START-OF-SELECTION.
CREATE OBJECT oref.
oref->m2( ).
Addition 5
... CREATE {PUBLIC|PROTECTED|PRIVATE}
Effect
The addition CREATE specifies the context in which the class class is instantiated – that is, where the statement CREATE OBJECT can be executed for this class and in which visibility section the instance constructor of the class can be declared.
◈ A class with the addition CREATE PUBLIC can be instantiated anywhere where the class is visible within the framework of the package concept.
◈ A class with the addition CREATE PROTECTED can only be instantiated in methods of its subclasses, methods of the class itself and methods of its friends.
◈ A class with the addition CREATE PRIVATE can only be instantiated in methods of the class itself or methods of its friends. This means, in particular, that it cannot be instantiated as an inherited component of subclasses.
Whether a subclass can be instantiated depends on its immediate superclass:
◈ Immediate subclasses of object, or classes with the addition CREATE PUBLIC inherit the addition CREATE PUBLIC implicitly. All CREATE additions that then overwrite the inherited addition can be specified explicitly.
◈ Immediate subclasses of classes with the addition CREATE PROTECTED inherit the addition CREATE PROTECTED implicitly. All CREATE additions that then overwrite the inherited addition can be specified explicitly.
◈ Immediate subclasses of classes with the addition CREATE PRIVATE that are not friends of the class inherit the addition CREATE NONE implicitly. They cannot be instantiated and no explicit CREATE additions can be specified. Immediate subclasses that are friends of the class inherit the addition CREATE PRIVATE implicitly. All CREATE additions can be specified for all superclasses that can instantiated as private using friends.
The statement METHODS constructor for the declaration of the instance constructor of a local class can be specified in all visibility sections which are of general instantiability or of the instantiability used in the addition CREATE. For global classes, only a declaration in the public visibility section is feasible, for technical reasons.
Notes
◈ It is best to make a class that can be instantiated as private a final class, since its subclasses cannot be instantiated unless they are friends of the class.
◈ It is best to declare the instance constructor of local classes in the visibility sector of the class that matches its instantiability, since this enables the components declared there to be used in the constructor interface.
Addition 6
... SHARED MEMORY ENABLED
Effect
The addition SHARED MEMORY ENABLED defines a shared memory-enabled class whose instances can be stored in shared memory as shared objects.
The addition SHARED MEMORY ENABLED can only be applied to a subclass if all its superclasses have been defined with this addition. Subclasses do not necessarily inherit this addition from their superclasses.
Notes
◈ The static attributes of a Shared Memory-enabled class are handled in the same way as a normal class, that is they are created in internal session of a program when the class is loaded. If different programs access the same shared objects, the static attributes of the corresponding classes exist multiple times and independently from each other in the programs.
◈ No events can be declared or handled in a shared-memory-enabled class. The statements [CLASS-]EVENTS and the addition FOR EVENT cannot be specified in the declaration part.
◈ For global shared memory-enabled classes, the addition SHARED MEMORY ENABLED is assigned by choosing the shared memory-enabled attribute in Class Builder. This applies in particular to the area root class of an area, which is always global.
◈ This addition should be specified only if it does not cause any problems. Problems occur with shared memory if:
◈ The class has static attributes which contain information about all the instances as a whole – such as the total number of instances.
◈ The class allocates its own memory internally – for example, using kernel methods.
Addition 7
... [GLOBAL] FRIENDS class1 class2 ... intf1 intf2 ...
Effect
The addition FRIENDS makes the classes class1 class2 ... or the interfaces intf1 intf2 ... friends of the class class. At the same time, all subclasses of the classes class1 class2 ..., all classes that implement one of the interfaces intf1 intf2 ..., and all interfaces that include one of the interfaces intf1 intf2 ... as a component interface become friends of the class class. At least one class or one interface must be specified.
The friends of a class have unrestricted access to all components of the class, regardless of the visibility section and the addition READ-ONLY. Friends can create instances of the class without any restrictions.
The friends of class are not automatically made friends of the subclasses of class. The addition FRIENDS does not make the class class a friend of the friends of the other class.
Without the addition GLOBAL, all classes and interfaces that are visible at this point can be specified for class1 class2... and intf1 intf2 .... If global classes and interfaces from the class library are made friends, make sure that the local classes of ABAP programs are not visible in these global classes. The components of a local class class cannot be accessed statically by these friends.
The addition GLOBAL is only allowed if the addition PUBLIC is also used – that is, where the class is a global class of a class pool. Other global classes and interfaces from the class library can be specified after GLOBAL FRIENDS. This addition is created when a global class is created by Class Builder if friends are entered on the appropriate tab.
Note
The addition FRIENDS must be specified as the last addition after all other additions.
Example
In this example, the interface i1 and therefore the implementing class c2 are friends of the class c1. The class c2 can instantiate c1 and access its private component a1.
INTERFACE i1.
...
ENDINTERFACE.
CLASS c1 DEFINITION CREATE PRIVATE FRIENDS i1.
PRIVATE SECTION.
DATA a1 TYPE c LENGTH 10 VALUE 'Class 1'.
ENDCLASS.
CLASS c2 DEFINITION.
PUBLIC SECTION.
INTERFACES i1.
METHODS m2.
ENDCLASS.
CLASS c2 IMPLEMENTATION.
METHOD m2.
DATA oref TYPE REF TO c1.
CREATE OBJECT oref.
cl_demo_output=>display_text( oref->a1 ).
ENDMETHOD.
ENDCLASS.
➥ PUBLIC SECTION
Syntax
PUBLIC SECTION.
Effect
This statement can only be used in the declaration part of a class. It defines the public visibility section of the class class. All components of the class that are declared after the statement PUBLIC SECTION are accessible from outside the class, in their subclasses, and in the class itself as long as this permitted by the package concept. Public methods in particular can be redefined in subclasses.
➥ PROTECTED SECTION
Syntax
PROTECTED SECTION.
Effect
This statement can only be used in the declaration part of a class. It defines the protected visibility section of the class class.
All components of the class declared in the area behind the statement PROTECTED SECTION can be addressed directly only in the subclasses of the class and in the class itself (plus its friends), if allowed by the package concept. Protected methods in subclasses can be redefined.
Notes
The class is the smallest encapsulation unit in ABAP Objects. This is the reason why a method cannot only use the protected components of its own class but also all instances of the same class.
In subclasses, it is not possible to access the protected components of the superclasses using reference variables of the type of the superclass, because otherwise an attribute of an object of the dynamic type of the superclass or another subclass could be changed. In the last case, a warning is produced by the extended syntax check.
A subclass cannot access the protected components of a subclass of a different branch of the inheritance hierarchy even though they are inherited from a shared superclass.
The declaration of attributes in the protected section does not prevent methods in subclasses or in the class itself from passing references to these attributes in the form of reference variables or field symbols, so that the attributes become visible and modifiable outside the protected section.
➥ PRIVATE SECTION
Syntax
PRIVATE SECTION.
Effect
This statement can only be used in the declaration part of a class. It defines the private visibility section of the class class. All components of the class defined in the area behind the PRIVATE SECTION statement can only be addressed in the class itself, and in its friends.
Notes
The class is the smallest encapsulation unit in ABAP Objects. This means that a method can use all private components of all instances of the same class, apart from the private components of its own class. An exception to this rule are subclasses that cannot access the private components of superclasses, if they are not their friends.
The declaration of attributes in the private section does not stop methods of the References class from declaring externally to these attributes in the form of reference variables or field symbol, and therefore making the attributes visible and modifiable outside the private section.
Private components declared in a class but not used statically there produce a warning in the extended program check.
➥ CLASS - components
The components of the classes are defined in the visibility sections. The following declaration statements are possible for components:
◈ TYPES, DATA, CLASS-DATA, CONSTANTS for data types and data objects
◈ METHODS, CLASS-METHODS, EVENTS, CLASS-EVENTS for methods and events
◈ INTERFACES for implementing interfaces and ALIASES for alias names for interface components
Note
All the components in a class are in one namespace. The name of a component must be unique to its type (data type, attribute, method, event, or alias name) within one class. The components of an implemented interface are marked with the prefix intf~ (name of the interface with interface component selector).
2. CLASS - IMPLEMENTATION
Syntax
CLASS class IMPLEMENTATION.
...
METHOD ...
...
ENDMETHOD.
...
ENDCLASS.
Effect
In the statement block CLASS class IMPLEMENTATION - ENDCLASS, the following methods of a class class must be implemented, in any order:
All concrete methods that are declared using METHODS or CLASS-METHODS in the declaration part of the class.
All concrete methods of interfaces that are specified by the statement INTERFACES in the declaration part of the class.
All methods inherited from superclasses that are specified by the statement METHODS ... REDEFINITION in the declaration part of the class.
The implementation of each method corresponds to a processing block METHOD - ENDMETHOD. No statements are allowed in the implementation part outside of method implementations. All components of the class can be accessed in an instance method implementation. All static components of the class can be accessed in a static method implementation. A component selector is not required for addressing components in the same class. Within the implementation of each instance method, there is an implicitly created, local reference variable named me available at runtime. It points to the current instance of the method.
When implementing methods declared in an interface bound by the class INTERFACES intf, the name of the method in METHOD must have either intf~ in front of it or use an alias name declared using ALIASES. The interface method must be declared in the interface. Otherwise, a syntax error will occur when local interfaces are used. If a global interface is specified using intf~, only a syntax warning is issued. In this way, the classes remain usable even after subsequent removal of the methods from the global interface, provided they have not used the methods themselves.
Notes
A class that does not need to implement any methods on the basis of its declaration part either has an empty implementation part or none at all.
Abstract methods in abstract classes cannot be implemented in the implementation part.
The implementation part of a class can only be specified in the context described under CLASS.
Example
In this example, three methods of the class c2 must be implemented. The method m1 in c1 is abstract and must not be implemented there.
INTERFACE i1.
METHODS m1.
ENDINTERFACE.
CLASS c1 DEFINITION ABSTRACT.
PROTECTED SECTION.
METHODS m1 ABSTRACT.
ENDCLASS.
CLASS c2 DEFINITION INHERITING FROM c1.
PUBLIC SECTION.
INTERFACES i1.
METHODS m2.
PROTECTED SECTION.
METHODS m1 REDEFINITION.
ENDCLASS.
CLASS c2 IMPLEMENTATION.
METHOD m1.
...
ENDMETHOD.
METHOD m2.
...
ENDMETHOD.
METHOD i1~m1.
...
ENDMETHOD.
ENDCLASS.
3. ENDCLASS
Syntax
ENDCLASS.
Effect
The statement ENDCLASS closes a class declaration introduced using
CLASS class DEFINITION
or a class implementation introduced using
CLASS class IMPLEMENTATION
4. CLASS - DEFERRED
Syntax
CLASS class DEFINITION DEFERRED [PUBLIC].
Effect
This variant of the statement CLASS is used to make the class class known, regardless of the location of the actual definition of the class in the program. It does not introduce a declaration part and must not be ended using ENDCLASS.
Without the addition PUBLIC, the statement makes the local class of its actual definition known before its actual definition. The program must contain a declaration part for class at a later point. Individual components of the class cannot be accessed before it is actually defined. This statement is required if a reference to a local class needs to be made before it is defined.
Using the addition PUBLIC, this variant makes a global class known and defers loading the class until the end of the current program unit. Individual components of the class can only be accessed after it has been loaded. This statement can be used to prevent unwanted recursions when making references to global classes.
Note
This variant of the statement CLASS can also only be specified in the context described under CLASS.
Example
In this example, the class c1 uses the class c2 and vice versa. This means that one of the classes must be made known before it is actually defined.
CLASS c1 DEFINITION DEFERRED.
CLASS c2 DEFINITION.
PUBLIC SECTION.
DATA c1ref TYPE REF TO c1.
ENDCLASS.
CLASS c1 DEFINITION.
PUBLIC SECTION.
DATA c2ref TYPE REF TO c2.
ENDCLASS.
One example of using the addition DEFERRED PUBLIC would be a type group in which a reference type is declared with a reference to a global class, which itself contains components with references to this reference type. In this situation, the entire class cannot be loaded before the type group, since the types are not yet known. After the statement DEFERRED PUBLIC, however, the class name can be specified after REF TO without the class having been loaded previously.
5. CLASS - LOCAL FRIENDS
Syntax
CLASS class DEFINITION
LOCAL FRIENDS class1 class2 ...
intf1 intf2 ...
Effect
This statement makes the local classes and interfaces class1 class2 ... and intf1 intf2 ... of a class pool friends of its global class class. At least one class or one interface must be specified.
This statement does not introduce a declaration part. It must not be ended with an ENDCLASS statement.
Notes
Declaring local classes of a class pool as friends of the global class is necessary, in particular, for local test classes that test the private components of the global class.
This variant of the statement CLASS can also only be listed in the context described under CLASS.
If the local classes and interfaces class1 class2 ... and intf1 intf2 ... are to be able to access all components of the global class class in their declaration part, the statement must first be specified in the class pool. Here, the local classes and interfaces must first be registered using CLASS - or INTERFACE - DEFERRED.
1.2.3 INTERFACE
Syntax Forms
Declaration of Interfaces
1. INTERFACE intf [PUBLIC].
[components]
ENDINTERFACE.
Advance Declaration of Interfaces
2. INTERFACE intf DEFERRED [PUBLIC].
Effect
The statement INTERFACE defines interfaces or declares them in advance.
◈ The definition of an interface consists of a declaration section that starts with INTERFACE and is ended using ENDINTERFACE. Unlike classes, an interface does not have an implementation section.
◈ Additional variants of INTERFACE without ENDINTERFACE are used for the advance declaration of interfaces in a program.
The statements INTERFACE and associated statements ENDINTERFACE can be specified only in the global context of a program. INTERFACE and ENDINTERFACE cannot be specified within classes, procedures, and processing blocks implemented internally as a procedure (event blocks for GET and AT SELECTION-SCREEN). This applies in particular to the variant of INTERFACE specified here, which is not closed using ENDINTERFACE.
Notes
◈ The definition or advance declaration of an interface is handled like other declaration statements (DATA, TYPE, ...). In a processing block without a local context, they are handled like global program declarations and do not end the processing block.
◈ The obsolete variant INTERFACE ... LOAD was used to load interfaces explicitly.
1. INTERFACE intf
Syntax
INTERFACE intf [PUBLIC].
[components]
ENDINTERFACE.
Addition:
... PUBLIC
Effect
The statement block INTERFACE - ENDINTERFACE defines an interface intf. Naming conventions apply to the name intf. The components of the interface are declared between INTERFACE and ENDINTERFACE.
An interface defined using INTERFACE can be implemented in classes and included in other interfaces using the statement INTERFACES.
Note
The definition of an interface can only be specified in the context described under INTERFACE.
Addition
... PUBLIC
Effect
The addition PUBLIC makes the interface intf a global interface of the class library. The addition PUBLIC can only be used for the global interface of an interface pool and is created by Class Builder when a global interface is created.
Example
In this example, an interface i1 is declared using three interface components a1, m1, and e1. The class c1 implements the interface and the interface components therefore become public components of the class, which can be addressed using the interface component selector (~).
INTERFACE i1.
DATA a1 TYPE string.
METHODS m1.
EVENTS e1 EXPORTING value(p1) TYPE string.
ENDINTERFACE.
CLASS c1 DEFINITION.
PUBLIC SECTION.
INTERFACES i1.
ENDCLASS.
CLASS c1 IMPLEMENTATION.
METHOD i1~m1.
RAISE EVENT i1~e1 EXPORTING p1 = i1~a1.
ENDMETHOD.
ENDCLASS.
1.1 INTERFACE - components
The following declaration statements are possible in interfaces for components:
◈ TYPES, DATA, CLASS-DATA, and CONSTANTS for data types and data objects
◈ METHODS, CLASS-METHODS, EVENTS, and CLASS-EVENTS for methods and events
◈ INTERFACES for the inclusion of component interfaces and ALIASES for alias names for components of interfaces
The only interface components that can be addressed without implementation of the interface in classes are data types and constants. The latter can be addressed using the name of the interface and the class component selector (=>).
Notes
◈ All components of an interface are in the same namespace. Within an interface, the name of a component must be unique, regardless of its type (data type, attribute, method, event, or alias name). The components of an included interface are identified by the prefix intf~ (the name of the interface with an interface component selector).
◈ Interfaces provide fewer variants than classes for declarations of methods using METHODS and CLASS-METHODS. More specifically, no constructors, test methods, or AMDP function implementations can be declared in interfaces for CDS table functions.
2. ENDINTERFACE
Syntax
ENDINTERFACE.
Effect
The statement ENDINTERFACE closes an interface definition introduced using INTERFACE.
3. INTERFACE - DEFERRED
Syntax
INTERFACE intf DEFERRED [PUBLIC].
Effect
This variant of the INTERFACE statement is used to declare the interface intf independently of the location of the actual definition in the program. It does not introduce a declaration part nor can it be completed using ENDINTERFACE. The meaning is the same as for the corresponding variants of the statement CLASS.
Note
This variant of the statement INTERFACE can also only be specified in the context described under INTERFACE
The components of classes and interfaces are declared in the declaration part of classes and interfaces. The components of a class are as follows:
◈ Data types and attributes
◈ Methods
◈ Events
◉ Data Types and Attributes
Attributes are the data objects of a class. The declaration of data objects of a class is also possible. The declaration of attributes and data types takes place using
◈ general statements which are also possible in other contexts:
1. TYPES
2. DATA
3. CONSTANTS
◈ a special statement which is only possible in classes:
1. CLASS-DATA
Syntax
CLASS-DATA attr [options].
Effect
The statement CLASS-DATA can only be used in the declaration part of a class or an interface. The statement declares a static attribute attr whose validity is not associated with instances of a class but with the class itself. All instances of the class and its subclasses access the same static attribute.
The naming conventions apply to the name attr. The syntax of the additions options is identical to the statement DATA for instance attributes (only the addition WITH HEADER LINE must not be used).
Notes
◈ Like all static components in the inheritance, the static attributes of a superclass exist in all subclasses. A static attribute that is visible externally can be addressed using the class component selector along with all the names of the classes in which it exists. This means that the class in which it is declared is always addressed, which, for example, has an impact on how the static constructor is executed. A change made to the static attribute applies to all classes in which it exists, independently of the addressing.
◈ Static attributes declared using CLASS-DATA can be accessed by using the class component selector only with class names, and not with interface names.
◈ The static attributes of a shared memory-enabled class are handled in the same way as a normal class, which means they are created in the internal session of a program when the class is loaded there. If a number of programs access the same shared objects, the static attributes of the corresponding classes exist more than once and independently of one another in the programs.
◈ Structured static attributes can be declared as a static box using the addition BOXED.
Example
In this example, the static attribute text of class c1 is accessed using the class component selector without having created an instance of the class.
CLASS c1 DEFINITION.
PUBLIC SECTION.
CLASS-DATA text TYPE string VALUE `Static data`.
ENDCLASS.
START-OF-SELECTION.
cl_demo_output=>display_text( c1=>text ).
◉ Methods
Methods are declared using the statements
◈ METHODS for instance methods
◈ CLASS-METHODS for static methods
that are only possible in the declaration part of classes and interfaces.
Methods determine the behavior of a class. Instance methods are declared by the statement METHODS. Static methods are declared by the statement CLASS-METHODS. The declaration defines the interface of a method. For special tasks there are different types of methods:
◈ General instance methods and static methods
◈ Functional instance methods and static methods
◈ Instance constructors and static constructors
◈ Event handlers and static event handlers
Also available, are the
◈ Test methods of ABAP Unit, which can only be declared as instance methods.
◈ AMDP methods, which are implemented in a database-specific language and not in ABAP.
1. METHODS
Syntax Forms
General Instance Methods
1. METHODS meth [ABSTRACT|FINAL]
|[DEFAULT IGNORE|FAIL]
[IMPORTING parameters [PREFERRED PARAMETER p]]
[EXPORTING parameters]
[CHANGING parameters]
[{RAISING exc1|RESUMABLE(exc1) exc2|RESUMABLE(exc2) ...}
|{EXCEPTIONS exc1 exc2 ...}].
Functional Instance Methods
2. METHODS meth [ABSTRACT|FINAL]
|[DEFAULT IGNORE|FAIL]
[IMPORTING parameters [PREFERRED PARAMETER p]]
[EXPORTING parameters]
[CHANGING parameters]
RETURNING VALUE(r) typing
[{RAISING exc1|RESUMABLE(exc1) exc2|RESUMABLE(exc2) ...}
|{EXCEPTIONS exc1 exc2 ...}].
Instance Constructors (Only in Classes)
3. METHODS constructor [FINAL]
[IMPORTING parameters [PREFERRED PARAMETER p]]
[{RAISING exc1|RESUMABLE(exc1) exc2|RESUMABLE(exc2) ...}
|{EXCEPTIONS exc1 exc2 ...}].
Event Handlers
4. METHODS meth [ABSTRACT|FINAL]
|[DEFAULT IGNORE|FAIL]
FOR EVENT evt OF {class|intf}
[IMPORTING p1 p2 ... [sender]].
Redefinition of Instance Methods (Only in Subclasses)
5. METHODS meth [FINAL] REDEFINITION.
Test Methods (Only in Test Classes)
6. METHODS meth [ABSTRACT|FINAL]
FOR TESTING
[{RAISING exc1|RESUMABLE(exc1) exc2|RESUMABLE(exc2) ...}].
Effect
The statement METHODS declares or redefines an instance method meth. For the name meth, the naming conventions apply.
Instance methods are bound to objects. To use instance methods, an object of the class must first be created. In instance methods, all components of the same class can be accessed without a component selector.
Use the variants of statement METHODS to distinguish between the following kinds of method declarations:
◈ General instance methods
The general form of the METHODS statement allows the definition of instance methods with any input and output parameters.
◈ Functional instance methods
Functional methods have exactly one return value and any number of formal parameters.
◈ Instance constructors
Instance constructors are methods with the given name constructor, which are called automatically when their class is instantiated. Constructors have any number of input parameters and no output parameters. They cannot be declared in interfaces.
◈ Event handlers
Event handlers are methods that, although they can be called directly with or in statements, are mainly called when an event of a class or an interface is raised. The only possible formal parameters of an event handler are input parameters, which have been defined as the output parameters of the event.
◈ Redefinition of instance methods
A method declared in a superclass can be redefined in a subclass as long as it is not flagged as final in the superclass. In a redefinition, the interface of the method is not changed.
◈ Definition of a test method
Test methods can be declared in test classes. They have no interface parameters and are called during ABAP Unit tests by the ABAP runtime environment. They cannot be declared in interfaces.
● METHODS - ABSTRACT, FINAL
Syntax
METHODS meth ABSTRACT|FINAL ...
Additions
1. ... ABSTRACT
2. ... FINAL
Effect
The additions ABSTRACT and FINAL make an instance method abstract or final. They cannot be used in interfaces, only in classes. All instance methods can be declared as abstract except for instance constructors. The addition FINAL can be used in all variants of the statement METHODS.
Addition 1
... ABSTRACT
Effect
Uses the addition ABSTRACT to define an abstract method meth. The addition ABSTRACT is allowed only in abstract classes, not in interfaces. An abstract method is not implemented in the implementation part of its class. To implement an abstract method, it must be redefined in a specific subclass using the addition REDEFINITION. Private methods cannot be redefined and can therefore not be declared as abstract.
Notes
⬥ Abstract methods can be defined in classes that are either abstract or final, but they can never be implemented and therefore are not usable.
⬥ Methods in interfaces are abstract implicitly, because interfaces do not contain method implementations.
⬥ With the exception of the instance constructor, concrete instance methods of a class can also call their abstract methods.
⬥ Static methods cannot be redefined and the addition ABSTRACT is not allowed in their declarations.
Addition 2
... FINAL
Effect
Uses the addition FINAL to define a final method meth. The addition FINAL is allowed only in classes, not in interfaces. A final method cannot be redefined in a subclass. In final classes, all methods are final automatically and the addition FINAL is not allowed. An instance constructor constructor is always final and FINAL can be specified but is not mandatory. When used together with the addition REDEFINITION, the addition FINAL closes a path of an inheritance tree.
Note
Static methods cannot be redefined and the addition FINAL is not allowed in their declarations.
● METHODS - DEFAULT
Syntax
METHODS meth DEFAULT IGNORE|FAIL ...
Effect
The addition DEFAULT makes the explicit implementation of an interface method optional and defines a default behavior for calls of non-implemented methods. It cannot be used in classes, only in interfaces. Any instance methods and static methods can be defined as optional except for constructors and test methods.
A class that implements an interface with the statement INTERFACES can implement its optional methods, but this is not mandatory. The additions IGNORE or FAIL define the behavior that applies when an optional interface method of an object or class is called at runtime and this object or class is not implemented explicitly.
◈ When a non-implemented optional interface method defined with the addition IGNORE is defined, the behavior is the same as when it is implemented with an empty body. In particular, all actual parameters are initialized that receive values from formal parameters using pass by value.
◈ Calls of a non-implemented optional interface method defined using the addition FAIL raise an exception of the class CX_SY_DYN_CALL_ILLEGAL_METHOD. If this exception is not handled, the runtime error CALL_METHOD_NOT_IMPLEMENTED occurs.
The default behavior defined using DEFAULT also applies to the redefinition of an inherited optional interface method using the addition REDEFINITION. A subclass that redefines an optional interface method does not need to implement this method explicitly. If the implementation is missing, the default behavior is applied along a path of the inheritance tree until an explicit implementation occurs.
Notes
◈ The default behavior defined using DEFAULT FAIL that applies to calls of a non-implemented optional method matches the behavior that applies when a non-implemented non-optional method of a global interface is called.
◈ If an optional interface method is redefined in a subclass, it needs to be implemented explicitly in this subclass as well. The default behavior does not usually meet expectations here.
Example
The class class implements the interface intf without implementing its optional methods. A call of the non-implemented static method m1 raises a (handled) exception due to the addition FAIL. A call of the non-implemented instance method m2 does not execute any statements due to the addition IGNORE, but does set their return value r to 0.
INTERFACE intf.
CLASS-METHODS m1 DEFAULT FAIL.
METHODS m2 DEFAULT IGNORE
RETURNING VALUE(r) TYPE i.
ENDINTERFACE.
CLASS class DEFINITION.
PUBLIC SECTION.
INTERFACES intf.
ALIASES m1 FOR intf~m1.
ALIASES m2 FOR intf~m2.
ENDCLASS.
CLASS class IMPLEMENTATION.
ENDCLASS.
DATA oref TYPE REF TO class.
START-OF-SELECTION.
TRY.
class=>m1( ).
CATCH cx_sy_dyn_call_illegal_method INTO DATA(exc).
cl_demo_output=>display( exc->get_text( ) ).
ENDTRY.
cl_demo_output=>display( NEW class( )->m2( ) ).
● METHODS - IMPORTING, EXPORTING, CHANGING, RAISING
Syntax
METHODS meth [ABSTRACT|FINAL]
|[DEFAULT IGNORE|FAIL]
[IMPORTING parameters [PREFERRED PARAMETER p]]
[EXPORTING parameters]
[CHANGING parameters]
[{RAISING exc1|RESUMABLE(exc1) exc2|RESUMABLE(exc2) ...}
|{EXCEPTIONS exc1 exc2 ...}].
Additions
1. ... IMPORTING parameters [PREFERRED PARAMETER p]
2. ... EXPORTING parameters
3. ... CHANGING parameters
4. ... RAISING exc1|RESUMABLE(exc1) exc2|RESUMABLE(exc2) ...
5. ... EXCEPTIONS exc1 exc2 ...
Effect
This statement declares a general instance method meth. The additions ABSTRACT and FINAL can be used to make the method of a class abstract or final. The addition DEFAULT is used to make an interface method optional.
The additions IMPORTING, EXPORTING and CHANGING define the parameter interface of the method. After every addition, the corresponding formal parameters are defined by a specification of the list parameters. The order of the additions is fixed.
The remaining additions define which exceptions are propagated or raised by the method.
Note
Within a method, the predicate expression IS SUPPLIED can be used to check whether an optional formal parameter was assigned an actual parameter when it was called.
Addition 1
... IMPORTING parameters [PREFERRED PARAMETER p]
Effect
IMPORTING defines input parameters. When the method is called, an appropriate actual parameter must be specified for every non-optional input parameter. The content of the actual parameter is passed to the input parameter when the call is made. The content of an input parameter for which pass-by-reference is defined cannot be changed in the method.
Use PREFERRED PARAMETER to identify an input parameter p1 p2 ... from the list parameters after IMPORTING as a preferred parameter. This can only be specified if all input parameters and input/output parameters are optional. The parameter specified after PREFERRED PARAMETER is set to optional implicitly. If the method is called using the syntax meth( a ) (standalone or functional), the actual parameter a is assigned to the preferred input parameter p.
Note
Although PREFERRED PARAMETER makes the parameter p implicitly optional, this parameter should be made explicitly optional using OPTIONAL or DEFAULT. Otherwise a syntax check warning is displayed.
Addition 2
... EXPORTING parameters
Effect
EXPORTING defines output parameters. When the method is called, an appropriate actual parameter can be specified for every output parameter. The content of an output parameter defined for pass-by-value is passed to the actual parameter after the method has been completed successfully.
Note
An output parameter defined for pass-by-reference behaves like an input/output parameter, which means that it is not initialized when the method is called. For this reason, no read should be performed on it before the first write. In addition, be careful when adding content to such parameters as, for example, when inserting rows into internal tables.
Addition 3
... CHANGING parameters
Effect
CHANGING defines input/output parameters. When the method is called, an appropriate actual parameter must be specified for every non-optional input/output parameter. The content of the actual parameter is passed to the input/output parameter at the call, and after the method has been completed, the content of the input/output parameter is passed to the actual parameter.
Example
The method read_spfli_into_table of this example has an input and an output parameter, which are typed fully by reference to ABAP Dictionary.
CLASS flights DEFINITION.
PUBLIC SECTION.
METHODS read_spfli_into_table
IMPORTING VALUE(id) TYPE spfli-carrid
EXPORTING flight_tab TYPE spfli_tab.
...
ENDCLASS.
Addition 4
... RAISING exc1|RESUMABLE(exc1) exc2|RESUMABLE(exc2) ...
Effect
The addition RAISING is used to declare the class-based exceptions exc1 exc2 ... that can be propagated from the method to the caller.
For exc1 exc2 ..., all exception classes that are visible at this point that are subclasses of CX_STATIC_CHECK or CX_DYNAMIC_CHECK can be specified here. The exception classes must be specified in ascending order with respect to their inheritance hierarchy. Each exception class may only be specified once.
The addition RESUMABLE declares an exception that can be propagated as a resumable exception. This means:
◈ A resumable exception is propagated as a resumable exception.
◈ The addition does not have any effect on a non-resumable exception.
◈ If a resumable exception is propagated with RAISING without the addition RESUMABLE, it thus becomes non-resumable.
If a superclass is declared as resumable, any subclasses must also be declared as resumable.
Exceptions in the categories CX_STATIC_CHECK and CX_DYNAMIC_CHECK must be explicitly declared, to prevent propagations from violating the interface. A violation of the interface raises the handleable exception CX_SY_NO_HANDLER. Exceptions of the category CX_NO_CHECK are always declared implicitly and with addition RESUMABLE.
Notes
◈ The declaration of exceptions of the category CX_STATIC_CHECK is checked statically in the syntax check. For exceptions of the category CX_DYNAMIC_CHECK, the check is not performed until runtime.
◈ In a method in which class-based exceptions are declared using the addition RAISING, the statement CATCH SYSTEM-EXCEPTIONS cannot be used. Instead, the relevant handleable exceptions should be handled in a TRY control structure.
◈ An exception that is raised as resumable in the method with RAISE RESUMABLE EXCEPTION, should also be declared as resumable in the interface, since the exception would otherwise lose this property when the method is exited.
Example
In the class math, any exceptions represented by the class CX_SY_ARITHMETIC_ERROR and its subclasses are propagated from within the method divide_1_by. If, for example, the input parameter operand is filled by the call with the value 0, the exception CX_SY_ZERODIVIDE is raised, propagated, and can, as shown in the example, be handled by the caller in a TRY control structure.
CLASS math DEFINITION.
PUBLIC SECTION.
METHODS divide_1_by
IMPORTING operand TYPE i
RETURNING value(result) TYPE decfloat34
RAISING cx_sy_arithmetic_error.
ENDCLASS.
CLASS math IMPLEMENTATION.
METHOD divide_1_by.
result = 1 / operand.
ENDMETHOD.
ENDCLASS.
DATA oref TYPE REF TO math.
DATA exc TYPE REF TO cx_sy_arithmetic_error.
DATA res TYPE decfloat34.
DATA text TYPE string.
START-OF-SELECTION.
CREATE OBJECT oref.
TRY.
res = oref->divide_1_by( 4 ).
text = res.
CATCH cx_sy_arithmetic_error INTO exc.
text = exc->get_text( ).
ENDTRY.
MESSAGE text TYPE 'I'.
Addition 5
... EXCEPTIONS exc1 exc2 ...
Effect
The addition EXCEPTIONS is used to define a list of non-class-based exceptions exc1 exc2... that can be raised by the statements RAISE or MESSAGE RAISING in the method. The names exc1 exc2 ... for the exceptions are freely definable and specified directly. Exceptions defined in this way are bound to the method (similar to formal parameters) and cannot be propagated.
If this type of exception is raised in a method and no return code was assigned to it in the addition EXCEPTIONS in the method call, a runtime error occurs.
The additions RAISING and EXCEPTIONS cannot be used simultaneously. As before, in a method whose interface defines non-class-based exceptions, the statement RAISE EXCEPTION or the addition THROW in a conditional expression cannot be used to raise class-based exceptions.
Note
For new developments, it is advisable to use class-based exceptions that are independent of the method in question.
Example
In the class math, for method divide_1_by, an exception arith_error is defined which is raised in the method by the statement RAISE if an arithmetic error occurs. If, for example, the input parameter operand is filled with value 0 by the call, the exception arith_error is raised in the internal method handling of exception CX_SY_ZERODIVIDE and handled after the call of the method by evaluating sy-subrc. The method cannot be called functionally due to the handling of the classic exception.
CLASS math DEFINITION.
PUBLIC SECTION.
METHODS divide_1_by
IMPORTING operand TYPE i
RETURNING VALUE(result) TYPE decfloat34
EXCEPTIONS arith_error.
ENDCLASS.
CLASS math IMPLEMENTATION.
METHOD divide_1_by.
TRY.
result = 1 / operand.
CATCH cx_sy_arithmetic_error.
RAISE arith_error.
ENDTRY.
ENDMETHOD.
ENDCLASS.
DATA res TYPE decfloat34.
DATA oref TYPE REF TO math.
START-OF-SELECTION.
CREATE OBJECT oref.
oref->divide_1_by( EXPORTING operand = 4
RECEIVING result = res
EXCEPTIONS arith_error = 4 ).
IF sy-subrc = 0.
cl_demo_output=>display_data( res ).
ELSE.
cl_demo_output=>display_text( 'Arithmetic error!' ).
ENDIF.
● METHODS - RETURNING
Syntax
METHODS meth [ABSTRACT|FINAL]
|[DEFAULT IGNORE|FAIL]
[IMPORTING parameters [PREFERRED PARAMETER p]]
[EXPORTING parameters]
[CHANGING parameters]
RETURNING VALUE(r) typing
[{RAISING exc1|RESUMABLE(exc1) exc2|RESUMABLE(exc2) ...}
|{EXCEPTIONS exc1 exc2 ...}].
Addition:
... RETURNING VALUE(r) typing
Effect
This statement declares a functional instance method meth The same applies to the additions ABSTRACT, FINAL, DEFAULT, IMPORTING, EXPORTING, CHANGING, RAISING, and EXCEPTIONS as to general instance methods.
A functional method can be called as a function in a suitable reading position.
Addition
... RETURNING VALUE(r) typing
Effect
Alongside any other formal parameters, a functional method has precisely one return value r declared using the addition RETURNING. The return value must be passed by value using VALUE and be fully typed using typing. In the typing check, special rules apply, depending on whether an explicit actual parameter is bound with RECEIVING or the functional method is used in an operand position.
Notes
◈ In functional method calls, a functional method obscures a predefined function with the same name. This case can occur only in the methods of the class of the functional method; however, a method should never have the same name as a predefined function.
◈ Functional methods are allowed as actual parameters of methods, which enables the option of nesting method calls in an operand position.
◈ Within a method, the predicate expression IS SUPPLIED can be used to check whether an actual parameter was assigned to the return value when the call was made. This is always the case in functional method calls.
● METHODS - Constructor
Syntax
METHODS constructor [FINAL]
[IMPORTING parameters [PREFERRED PARAMETER p]]
[{RAISING exc1|RESUMABLE(exc1) exc2|RESUMABLE(exc2) ...}
|{EXCEPTIONS exc1 exc2 ...}].
Additions
1. ... IMPORTING parameters
2. ... RAISING exc1|RESUMABLE(exc1) exc2|RESUMABLE(exc2) ...
3. ... EXCEPTIONS exc1 exc2 ...
4. ... FINAL
Effect
This statement declares the instance constructor constructor of a class. In a local class, it can be specified in all visibility sections that have more general instantiability than or the same instantiability specified in the CREATE addition of the statement CLASS DEFINITION:
CREATE PUBLIC | CREATE PROTECTED | CREATE PRIVATE | |
PUBLIC SECTION | X | X | X |
PROTECTED SECTION | - | X | X |
PRIVATE SECTION | - | - | X |
In a global class, the instance constructor must always be declared in the public visibility section, for technical reasons. In principle, the constructor can be declared in the same visibility sections as in the table above, however this can cause unexpected syntax errors when the class is used, due to the way it is organized internally.
Each class has a predefined method called constructor. By declaring this explicitly, the interface of the method constructor can be defined specifically for a class, and its functions can be implemented. Without explicit declaration, the instance constructor assumes the parameter interface of the direct superclass, and calls it implicitly.
If the instance constructor is implemented in a subclass, the instance constructor of the superclass must be called explicitly using super->constructor, even if the latter is not explicitly declared. The only exceptions to this are direct subclasses of the root node object. The following restrictions apply before the superclass constructor is called:
◈ The instance constructor does not have access to the instance components of its class. The self-reference me-> cannot be used. The static components of its class can be accessed only directly.
◈ Befor the superclass constructor is called, an instance constructor cannot be exited using statements such as RETURN or CHECK.
After the superclass constructure has been called, the self-reference me-> can be used and instance components can be accessed.
For each instance of a class, the instance constructor is called only once using the statement CREATE OBJECT immediately after it has been created. For the call, appropriate actual parameters must be assigned to all non-optional input parameters, return codes can be assigned to non-class-based exceptions, and class-based exceptions can be declared. It is not possible to call the instance constructor explicitly, except when calling the superclass constructors using super->constructor in the redefined constructor of a subclass.
When an instance constructor is executed, the current instance temporarily assumes the type of the class in which the constructor is defined. This has the following consequences:
◈ If methods are called when a superclass constructor is executed, the implementations of the superclass are executed and not the redefinitions of subclasses. When specified for addressing a redefined method in a subclass that has just been created, me-> is ignored.
◈ Abstract methods of the same class cannot be called in an instance constructor.
◈ When a superclass constructor is executed, attempts to access components of the subclass using a down cast produce a runtime error.
Notes
◈ Instance constructors are an exception to the rule that all public components on a path in the inheritance hierarchy are in the same namespace. The instance constructor of each class has its own interface and its own implementation. An instance constructor cannot be redefined.
◈ Instance constructors are declared in the public visibility section of a class purely for technical reasons. The actual visibility is controlled by the addition CREATE {PUBLIC|PROTECTED|PRIVATE} of the statement CLASS DEFINITION. It is advisable to declare the instance constructor of a local class in the visibility section which matches its instantiability, because this allows the components declared there to be used in the constructor interface. For global classes, only the public section is feasible, however.
◈ Before the superclass constructor is called, static components of the same class cannot be accessed using me-> in the instance constructor of a subclass. Access to the components without using me-> or using the class name and the class component selector => is always possible.
Addition 1
... IMPORTING parameters
Addition 2
... RAISING exc1|RESUMABLE(exc1) exc2|RESUMABLE(exc2) ...
Addition 3
... EXCEPTIONS exc1 exc2 ...
Effect
The addition IMPORTING can be used to define input parameters according to the same rules as for general methods. The additions RAISING and EXCEPTIONS for the declaration of class-based exceptions or the definition of non-class-based exceptions also have the same meaning as for general methods.
Note
When the instance constructor is executed, the same applies for resumable exceptions as for all other methods. If processing can be resumed successfully, the creation of the object can also be resumed.
Addition 4
... FINAL
Effect
Instance constructors are implicitly final. The addition FINAL can be specified, but it is not necessary.
Example
In this example, the class c2 inherits from the class c1. In both classes, the instance constructor constructor is declared explicitly. It must therefore be implemented in both classes and the implementation in c2 must include the call of the superclass constructor.
CLASS c1 DEFINITION.
PUBLIC SECTION.
METHODS constructor IMPORTING p1 TYPE any.
...
ENDCLASS.
CLASS c2 DEFINITION INHERITING FROM c1.
PUBLIC SECTION.
METHODS constructor IMPORTING p2 TYPE any.
...
ENDCLASS.
CLASS c1 IMPLEMENTATION.
METHOD constructor.
...
ENDMETHOD.
ENDCLASS.
CLASS c2 IMPLEMENTATION.
METHOD constructor.
...
super->constructor( p2 ).
...
ENDMETHOD.
ENDCLASS.
● METHODS - FOR EVENT
Syntax
METHODS meth [ABSTRACT|FINAL]
|[DEFAULT IGNORE|FAIL]
FOR EVENT evt OF {class|intf}
[IMPORTING p1 p2 ... [sender]].
Addition:
... IMPORTING p1 p2 ... [sender]
Effect
This statement declares the instance method meth as an event handler for the event evt of class class or interface intf. For class and intf, classes and interfaces can be specified that are visible in this position and that contain an event evt as a component that is visible here.
The visibility section of the event handler cannot be more general than the visibility section of the event. Otherwise properties of the method would be defined in a visibility section more restricted than the method itself.
If the event evt is an instance event, the event handler meth can handle it for all objects whose classes match class or that are subclasses of class or which implement the interface intf directly or by using a superclass. If the event is a static event, the event handler meth can handle it for the class class and its subclasses or for all classes that implement the interface intf.
◈ Using the additions ABSTRACT and FINAL, event handlers can either be made abstract or final just like general methods in classes.
◈ The addition DEFAULT can be used to make event handlers optional, just like general methods in interfaces.
Notes
◈ To ensure that an event handler handles a triggered event, it must be registered with the statement SET HANDLER.
In event handlers, no class-based exceptions can be declared using RAISING. See Class-Based Exceptions in Event Handlers.
◈ When event handlers are declared for static events, it must be noted that these events are generally triggered in static methods as well. In a method of this type, the class in which the method is declared is always the trigger, and not the subclass in which the method was called (or called using the name of the subclass).
Addition
... IMPORTING p1 p2 ... [sender]
Effect
The addition IMPORTING defines the input parameters of the event handler. For p, only those names of formal parameters can be specified that are defined as output parameters of the event by using the addition EXPORTING of the statement EVENTS or CLASS-EVENTS. This is done in the declaration of the event evt in the class class or in the interface intf. The additions TYPE or LIKE and OPTIONAL or DEFAULT are not possible. The typing of the input parameters, whether they are optional, and any replacement parameters are all defined in the declaration of the event. Not all output parameters of the event need to be specified.
If evt is an instance event, a formal parameter called sender can be defined as an input parameter of an event handler, in addition to the explicitly defined output parameters of the event. The formal parameter sender is an implicit output parameter of every instance event. It is fully typed as a reference variable, which itself has the class class or the interface intf as a static type, as specified in the declaration of the event handler after EVENT evt OF. If the event handler is called by an instance event, a reference to the triggering object is passed to it in sender.
Note
Each event handler determines the type of its formal parameter sender.
Example
The class picture contains an event handler handle_double_click for the instance event picture_dblclick of the global class cl_gui_picture. The event handler inherits two explicit output parameters of the event and the implicit parameter sender as input parameters.
CLASS picture DEFINITION.
PUBLIC SECTION.
METHODS handle_double_click
FOR EVENT picture_dblclick OF cl_gui_picture
IMPORTING mouse_pos_x mouse_pos_y sender.
ENDCLASS.
CLASS picture IMPLEMENTATION.
METHOD handle_double_click.
...
ENDMETHOD.
ENDCLASS.
● METHODS - REDEFINITION
Syntax
METHODS meth [FINAL] REDEFINITION.
Addition:
... FINAL
Effect
This statement is possible only in subclasses and redefines an inherited instance method meth. It dictates that the method meth must be reimplemented in the implementation part of the subclass. The new implementation in the current class obscures the implementation of the superclass. The redefined method accesses the private components of the redefined class and not any private components of the same name in the superclass. In the redefined method, the implementation of the direct superclass can be called using super->meth. The redefinition is valid for the subclasses of the redefined class until the method is redefined again.
With the exception of the instance constructor, meth can be specified as any non-final instance method declared in the public or protected visibility section of a superclass of the current class. In particular, meth can be an abstract method of an abstract superclass. The redefinition must happen in the same visibility section as the method declaration. The interface and the category of the method (a general or functional instance method or event handler) are not changed in a redefinition. Private methods in superclasses cannot be redefined.
Notes
◈ Every object reference that points to an object of a subclass, independently of its static type, addresses the redefined methods. This applies in particular to the self reference me->.
◈ When an instance constructor of a superclass is executed as part of the creation of an object, the method implementations of the superclass are always called and not the redefined methods of the subclass. Specifying the self-reference me-> does not have any affect at this time.
◈ In the redefinition of a method of an interface, an alias name of the class defined using ALIASES can be specified for meth.
◈ The explicit implementation can be omitted when redefining an optional interface method declared using DEFAULT. Instead, the default behavior defined using DEFAULT applies in calls from the current subclass. This is not recommended however. The default behavior is often unwanted, particularly if an explicit implementation already exists in a preceding superclass.
Addition
... FINAL
A method can be redefined repeatedly along a path in the inheritance tree until the addition FINAL is used in the redefinition. The method is then final starting with the current class and can no longer be redefined in its subclasses.
Example
In this example, the method m1 of superclass c1 is redefined in subclass c2, where the original implementation is called using super->m1. Both methods use the private attribute a1 of the respective class. When calling using the reference variable oref, which has the static type c1 and the dynamic type c2, the redefined method is executed.
CLASS c1 DEFINITION.
PUBLIC SECTION.
METHODS m1 IMPORTING p1 TYPE string.
PRIVATE SECTION.
DATA a1 TYPE string VALUE `c1: `.
ENDCLASS.
CLASS c2 DEFINITION INHERITING FROM c1.
PUBLIC SECTION.
METHODS m1 REDEFINITION.
PRIVATE SECTION.
DATA a1 TYPE string VALUE `c2: `.
ENDCLASS.
CLASS c1 IMPLEMENTATION.
METHOD m1.
a1 = a1 && p1.
cl_demo_output=>write_data( a1 ).
ENDMETHOD.
ENDCLASS.
CLASS c2 IMPLEMENTATION.
METHOD m1.
super->m1( p1 ).
a1 = a1 && p1.
cl_demo_output=>write_data( a1 ).
ENDMETHOD.
ENDCLASS.
DATA oref TYPE REF TO c1.
START-OF-SELECTION.
oref = NEW c2( ).
oref->m1( `...` ).
cl_demo_output=>display( ).
● METHODS - parameters
Syntax
... { VALUE(p1) | REFERENCE(p1) | p1 }
typing [OPTIONAL|{DEFAULT def1}]
{ VALUE(p2) | REFERENCE(p2) | p2 }
typing [OPTIONAL|{DEFAULT def2}]
...
Addition:
... OPTIONAL|{DEFAULT def}
Effect
Defines formal parameters p1 p2 ... for methods.
VALUE or REFERENCE are used to define whether a parameter p1 p2 ... is passed by value or by reference. If only one name p1 p2 ... is specified, the parameter is passed by reference by default. An input parameter passed by reference must not be changed in the method.
If the addition typing is used, every formal parameter must be typed. The syntax of typing is described in Typing Syntax. The typing of a formal parameter causes the data type to be checked against the typing when an actual parameter is passed. The typing also defines at which operand positions the formal parameter can be used in the method.
Note
If a formal parameter is typed as a reference variable and cannot be changed in the procedure, the type check is performed in the same way as for an up cast. If it can be changed in the procedure, the actual parameter must be compatible with the formal parameter.
Addition
... OPTIONAL|{DEFAULT def}
Effect
OPTIONAL or DEFAULT can be used to define input parameters and input/output parameters as optional parameters, where DEFAULT can be used to specify a replacement parameter def1, def2, ... No actual parameter needs to be specified for an optional parameter when the method is called. The addition OPTIONAL is used to initialize a formal parameter in a type-friendly way, but the addition DEFAULT passes the value and type of the replacement parameter def1 def2 ... to the formal parameter. The replacement parameter def1 def2 ... can be specified as any appropriate data object at this position except for components of boxed components.
If no actual parameter is specified for a generically typed formal parameter with the addition OPTIONAL when it is called, the type of the formal parameter is completed according to fixed rules.
2. CLASS-METHODS
Syntax Forms
General Static Methods
1. CLASS-METHODS meth [DEFAULT IGNORE|FAIL]
[IMPORTING parameters [PREFERRED PARAMETER p]]
[EXPORTING parameters]
[CHANGING parameters]
[{RAISING exc1|RESUMABLE(exc1) exc2|RESUMABLE(exc2) ...}
|{EXCEPTIONS exc1 exc2 ...}].
Functional Static Methods
2. CLASS-METHODS meth [DEFAULT IGNORE|FAIL]
[IMPORTING parameters [PREFERRED PARAMETER p]]
[EXPORTING parameters]
[CHANGING parameters]
RETURNING VALUE(r) typing
[{RAISING exc1|RESUMABLE(exc1) exc2|RESUMABLE(exc2) ...}
|{EXCEPTIONS exc1 exc2 ...}].
Static Constructors (Only in Classes)
3. CLASS-METHODS class_constructor.
Event Handlers
4. CLASS-METHODS meth [DEFAULT IGNORE|FAIL]
FOR EVENT evt OF {class|intf}
[IMPORTING p1 p2 ... [sender]].
AMDP Function Implementations for CDS Table Functions (Only in Classes)
5. CLASS-METHODS meth FOR TABLE FUNCTION cds_entity.
Effect
The statement CLASS-METHODS declares a static method meth. The naming conventions apply to the name meth.
Using the class component selector (=>), static methods can be used independently of objects. In static methods, the static components of the class or its superclasses can be accessed only if the component selector is not used.
The variants of the statement CLASS-METHODS distinguish different types of method declaration:
◈ General static methods
The most general form of the statement CLASS-METHODS allows static methods in classes and interfaces to be declared with any number of input and output parameters.
◈ Functional static methods
Functional methods of classes and interfaces have exactly one return value and any number of formal parameters.
◈ Static constructors
Static constructors of classes are methods with the predefined name class_constructor that are called automatically before their class is first used. Static constructors do not have a parameter interface and cannot be declared in interfaces.
◈ Static event handlers
Static event handlers are static methods of classes and interfaces that are called by an event of a class or an interface. The only possible formal parameters of an event handler are input parameters that were defined as the output parameters of the event.
◈ AMDP function implementations
AMDP function implementations declared using the addition FOR TABLE FUNCTION implement a CDS table function in an AMDP class. The formal parameters are determined using the CDS table function. An AMDP function implementation cannot be declared in an interface.
Note: Like all static components in the inheritance, the static methods of a superclass exist in all subclasses. A static method is always executed in the class in which it was declared. A static method that is visible from outside can be called using the class component selector, as can all names and classes in which it exists. The class in which it was declared is always the one that is addressed. This modifies the way the static constructor or the event handlers are executed.
2.1 CLASS-METHODS - IMPORTING, EXPORTING, CHANGING, RAISING
Syntax
CLASS-METHODS meth [DEFAULT IGNORE|FAIL]
[IMPORTING parameters [PREFERRED PARAMETER p]]
[EXPORTING parameters]
[CHANGING parameters]
[{RAISING exc1|RESUMABLE(exc1) exc2|RESUMABLE(exc2) ...}
|{EXCEPTIONS exc1 exc2 ...}].
Effect
This statement declares a general static method meth. The additions define make an interface method optional, define the parameter interface of the method, and specify the exceptions that the method can raise and propagate. The additions have the same syntax and meaning as those for general instance methods.
Notes
◈ Static methods cannot be redefined, which means that they cannot be flagged as abstract or final.
◈ Static methods are always executed in the class in which they were declared, even if they were called in subclasses or using the names of subclasses.
Syntax
CLASS-METHODS meth [DEFAULT IGNORE|FAIL]
[IMPORTING parameters [PREFERRED PARAMETER p]]
[EXPORTING parameters]
[CHANGING parameters]
RETURNING VALUE(r) typing
[{RAISING exc1|RESUMABLE(exc1) exc2|RESUMABLE(exc2) ...}
|{EXCEPTIONS exc1 exc2 ...}].
Effect
This statement declares a functional static method meth. The additions have exactly the same syntax and meaning as those for functional instance methods.
Example
The class circle contains two functional static methods, circumference and area, which work with the constant pi.
CLASS circle DEFINITION.
PUBLIC SECTION.
CONSTANTS pi TYPE decfloat34
VALUE '3.141592653589793238462643383279503'.
CLASS-METHODS: circumference IMPORTING r TYPE decfloat34
RETURNING value(c) TYPE decfloat34,
area IMPORTING r TYPE decfloat34
RETURNING value(a) TYPE decfloat34.
ENDCLASS.
CLASS circle IMPLEMENTATION.
METHOD circumference.
c = 2 * pi * r.
ENDMETHOD.
METHOD area.
a = pi * r ** 2.
ENDMETHOD.
ENDCLASS.
DATA: circ TYPE decfloat34,
area TYPE decfloat34,
radius TYPE decfloat34.
START-OF-SELECTION.
radius = '1.00'.
circ = circle=>circumference( radius ).
area = circle=>area( radius ).
2.3 CLASS-METHODS - class_constructor
Syntax
CLASS-METHODS class_constructor.
Effect
This statement declares the static constructor class_constructor of a class. It can only be used in the public visibility section of the declaration part of a class.
Each class has a predefined method class_constructor in its public visibility section. Its functions can be implemented class-specifically by explicit declaration. Without explicit declaration, the static constructor is empty.
The static constructor is called automatically exactly once per class and internal session before the class is first accessed. An access to the class is the creation of an instance of the class or the addressing of a static component using the class component selector.
When a subclass is first accessed, the inheritance tree is searched for the next-highest superclass whose static constructor was not yet called. Then the static constructor of this superclass is executed followed by those of all subsequent subclasses up to the subclass in question. The static constructor must be fully executed, otherwise a runtime error occurs.
Like all static methods, the static constructor can only access the static components of its class. Furthermore, the static constructor cannot explicitly address its own class.
Notes
◈ Like instance constructors, static constructors are also an exception to the rule that all public components along a path in the inheritance tree are in one namespace.
◈ The point at which the static constructor is called has not yet been finalized. It is only possible to ensure that it is called before the class is accessed for the first time. For this reason, static methods may be executed before the static constructor was ended.
◈ The execution order of static constructors is dependent on the program flow. Static constructors must be implemented so that they can be executed in any order.
◈ In static constructors, class-based exceptions cannot be declared using RAISING, since it is generally not specified whether the consumer of a class is the first consumer and whether or not this consumer must handle exceptions propagated by the static constructor.
◈ If a static component of a superclass is addressed using the name of a subclass, the superclass is addressed and its static constructor is executed, but not the static constructor of the subclass.
◈ An unsuccessful dynamic access to a nonexistent component of a class does not count as an access to the class and the static constructor is not executed in this case.
Example
When a class is first accessed, the static constructor of this class uses the system field sy-repid to set the static attribute access_program for the name of the program of an internal session that uses the class first.
CLASS some_class DEFINITION.
PUBLIC SECTION.
CLASS-METHODS class_constructor.
PRIVATE SECTION.
CLASS-DATA access_program TYPE sy-repid.
ENDCLASS.
CLASS some_class IMPLEMENTATION.
METHOD class_constructor.
access_program = sy-repid.
ENDMETHOD.
ENDCLASS.
Syntax
CLASS-METHODS meth [DEFAULT IGNORE|FAIL]
FOR EVENT evt OF {class|intf}
[IMPORTING p1 p2 ...[sender]].
Effect
This statement declares the static method meth as the event handler for the event evt of the class class or the interface intf. The syntax and meaning of the additions are identical to the declaration of instance methods as event handlers.
Static event handlers can be called by the event evt independently of an instance of the class.
Example
The class dialog_box defines a static event handler close_box for the event raised when the user chooses to close a Control Framework (CFW) dialog box.
CLASS dialog_box DEFINITION.
PUBLIC SECTION.
METHODS constructor.
...
PRIVATE SECTION.
CLASS-DATA open_boxes TYPE i.
CLASS-METHODS close_box
FOR EVENT close OF cl_gui_dialogbox_container
IMPORTING sender.
...
ENDCLASS.
CLASS dialog_box IMPLEMENTATION.
METHOD constructor.
... " create a dialogbox
open_boxes = open_boxes + 1.
ENDMETHOD.
METHOD close_box
... " close the dialogbox referred by sender
open_boxes = open_boxes - 1.
ENDMETHOD.
ENDCLASS.
◉ Events
Events are declared using the statements EVENTS and CLASS-EVENTS, which are possible only in the declaration part of classes and interfaces. Declaring an event in a class means that the methods of the class trigger the event and can therefore cause execution of event handlers. In the declaration, you can define output parameters for an event, for which actual parameters are transferred to the event handler when the event is executed.
The statement EVENTS declares instance events. Instance events are linked to objects. They can only be triggered in instance methods of the same class.
The statement CLASS-EVENTS declares static events. Static events are not linked to objects. They can be triggered in all methods of the same class.
1. EVENTS
Syntax
EVENTS evt [EXPORTING parameters].
Addition:
... EXPORTING parameters
Effect
Declares an instance event evt in a class or interface. The Naming conventions apply to the name evt. Using the statement RAISE EVENT, the instance event evt can be raised in any instance method of the same class, or of any class that implements the interface, as well as in the instance methods of subclasses (if they are visible there).
Addition
... EXPORTING parameters
Effect
The addition EXPORTING defines the parameter interface of the event evt. An event can only have output parameters parameters that are passed by value.
When an event handler is declared using the addition FOR EVENT OF of the statement METHODS or CLASS-METHODS, the output parameters of the event are defined as the input parameters of the event handler. The properties of the input parameters are applied from the output parameters defined in EVENTS.
As well as the output parameters defined explicitly using EXPORTING, each instance event has an implicit output parameter, sender. This output parameter has the type reference variable. When the event is raised using RAISE EVENT, the reference to the raising object is implicitly assigned to sender.
The static type of the input parameter sender is defined for every event handler by the object type (class or interface) that is specified after the addition FOR EVENT OF of the statement METHODS or CLASS-METHODS.
Note
The dynamic type of the implicit formal parameter sender is always the class of the object in which the event is raised.
Example
In the interface window, three events are declared, each with an explicit non-optional output parameter status. The class dialog_window implements the interface window. The interface window_handler contains event handlers, which import both the explicit parameters and the implicit parameter sender. The static type of the input parameter sender is the class dialog_window.
INTERFACE window.
EVENTS: minimize EXPORTING VALUE(status) TYPE i,
maximize EXPORTING VALUE(status) TYPE i,
restore EXPORTING VALUE(status) TYPE i.
ENDINTERFACE.
CLASS dialog_window DEFINITION.
PUBLIC SECTION.
INTERFACES window.
ENDCLASS.
INTERFACE window_handler.
METHODS: minimize_window
FOR EVENT window~minimize OF dialog_window
IMPORTING status sender,
maximize_window
FOR EVENT window~maximize OF dialog_window
IMPORTING status sender,
restore
FOR EVENT window~restore OF dialog_window
IMPORTING status sender.
ENDINTERFACE.
2. CLASS-EVENTS
Syntax
CLASS-EVENTS evt [EXPORTING parameters] .
Addition:
... EXPORTING parameters
Effect
This statement declares a static event evt in a class or interface. The Naming conventions apply to the name evt. The static event evt can be raised in all methods of the same class, or a class that implements the interface, and in the methods of subclasses (if it is visible there) using the statement RAISE EVENT.
Note
An event handler for which a subclass is declared for a static event, which is inherited from a superclass, can only react to this if the event is raised by a method of the subclass or one of its subclasses. If the event is raised in a static method of a superclass, it is not handled, even if the method is called in a subclass or if the name of the subclass is specified.
Addition
... EXPORTING parameters
Effect
The addition EXPORTING defines the parameter interface of the event evt. The syntax and meaning of the parameters additions correspond with definition of instance events using the statement EVENTS.
Note
Static events have no implicit formal parameter sender.
3. EVENTS - parameters
Syntax
... VALUE(p1) typing [OPTIONAL|{DEFAULT def1}]
VALUE(p2) typing [OPTIONAL|{DEFAULT def2}]
...
Effect
The syntax of the additions VALUE, OPTIONAL, and DEFAULT and the typing using typing corresponds to the definition of formal parameters in the interface of methods.
When an event is raised using RAISE EVENT, suitable actual parameters must be specified for all non-optional output parameters; these actual parameters are optional for all optional output parameters. Optional parameters for which no actual parameter has been specified are set to their type-friendly initial value or to the replacement parameter def1 def2 ...
4. Inheritance Events
The example demonstrates the behavior of inheritance events.
Source Code
REPORT demo_event_inheritance.
CLASS c1 DEFINITION.
PUBLIC SECTION.
CLASS-EVENTS ce1.
CLASS-METHODS cm1.
EVENTS ie1.
METHODS im1.
ENDCLASS.
CLASS c2 DEFINITION INHERITING FROM c1.
PUBLIC SECTION.
CLASS-METHODS cm2.
METHODS im2.
ENDCLASS.
CLASS c3 DEFINITION INHERITING FROM c2.
PUBLIC SECTION.
CLASS-METHODS cm3.
METHODS im3.
ENDCLASS.
CLASS c4 DEFINITION.
PUBLIC SECTION.
CLASS-METHODS cm4 FOR EVENT ce1 OF c2.
METHODS im4 FOR EVENT ie1 OF c2.
ENDCLASS.
CLASS event_demo DEFINITION.
PUBLIC SECTION.
CLASS-DATA handle_flag TYPE c LENGTH 1.
CLASS-METHODS main.
ENDCLASS.
CLASS event_demo IMPLEMENTATION.
METHOD main.
DATA oref1 TYPE REF TO c1.
DATA oref2 TYPE REF TO c2.
DATA oref3 TYPE REF TO c3.
DATA oref4 TYPE REF TO c4.
DATA(out) = cl_demo_output=>new(
)->begin_section( 'Static event' ).
SET HANDLER c4=>cm4.
c1=>cm1( ).
out->write( |c1=>cm1( ): { handle_flag }| ).
c2=>cm1( ).
out->write( |c2=>cm1( ): { handle_flag }| ).
c3=>cm1( ).
out->write( |c3=>cm1( ): { handle_flag }| ).
c2=>cm2( ).
out->write( |c2=>cm2( ): { handle_flag }| ).
c3=>cm2( ).
out->write( |c3=>cm2( ): { handle_flag }| ).
c3=>cm3( ).
out->write( |c3=>cm3( ): { handle_flag }| ).
out->next_section( 'Instance event' ).
CREATE OBJECT: oref1, oref2, oref3, oref4.
SET HANDLER oref4->im4 FOR ALL INSTANCES.
oref1->im1( ).
out->write( |oref1->im1( ): { handle_flag }| ).
oref2->im1( ).
out->write( |oref2->im1( ): { handle_flag }| ).
oref3->im1( ).
out->write( |oref3->im1( ): { handle_flag }| ).
oref2->im2( ).
out->write( |oref2->im2( ): { handle_flag }| ).
oref3->im2( ).
out->write( |oref3->im2( ): { handle_flag }| ).
oref3->im3( ).
out->write( |oref3->im3( ): { handle_flag }| ).
out->display( ).
ENDMETHOD.
ENDCLASS.
START-OF-SELECTION.
event_demo=>main( ).
CLASS c1 IMPLEMENTATION.
METHOD cm1.
CLEAR event_demo=>handle_flag.
RAISE EVENT ce1.
ENDMETHOD.
METHOD im1.
CLEAR event_demo=>handle_flag.
RAISE EVENT ie1.
ENDMETHOD.
ENDCLASS.
CLASS c2 IMPLEMENTATION.
METHOD cm2.
CLEAR event_demo=>handle_flag.
RAISE EVENT ce1.
ENDMETHOD.
METHOD im2.
CLEAR event_demo=>handle_flag.
RAISE EVENT ie1.
ENDMETHOD.
ENDCLASS.
CLASS c3 IMPLEMENTATION.
METHOD cm3.
CLEAR event_demo=>handle_flag.
RAISE EVENT ce1.
ENDMETHOD.
METHOD im3.
CLEAR event_demo=>handle_flag.
RAISE EVENT ie1.
ENDMETHOD.
ENDCLASS.
CLASS c4 IMPLEMENTATION.
METHOD cm4.
event_demo=>handle_flag = 'X'.
ENDMETHOD.
METHOD im4.
event_demo=>handle_flag = 'X'.
ENDMETHOD.
ENDCLASS.
Description
In a c1 superclass, a static event ce1 and an instance event ie1 are declared. The superclass c1, and its subclass c2, and its subclass c3, each contain a static method and an instance method to trigger events.
In the c4 class, event handlers are declared in c2 for the events inherited from c1. The main method of the event_demo class registers events and calls all methods which can trigger events, whereby different possibilities are used to address the methods. The output displays an "X" after the method call for a handled event.
1. The event handler cm4, declared for the c2 class, can only handle events which are triggered in this class or in its subclasses. Events which are triggered by the static method cm1 in c1, are not handled, irrelevant of the class name which is specified for the call (also refer to Inheritance and Static Components).
2. The event handler im4, declared for the c2 class, can also only handle events which are triggered in this class or in its subclasses. Unlike when calling static methods, the class of the object is always addressed when addressing an object using an object reference, and triggered events in the inherited method im1 of the c2 and c3 classes are handled.
◉ Implementing and including interfaces
Interfaces can be implemented by classes using the statement
⟹ INTERFACES
or can be included by other interfaces.
Alias names can be defined for interface components using the statement
⟹ ALIASES
1. INTERFACES
Syntax Forms
Implementing Interfaces in Classes
1. INTERFACES intf
[PARTIALLY IMPLEMENTED]
{ {[ABSTRACT METHODS meth1 meth2 ... ]
[FINAL METHODS meth1 meth2 ... ]}
| [ALL METHODS {ABSTRACT|FINAL}] }
[DATA VALUES attr1 = val1 attr2 = val2 ...].
Integrating Interfaces into Interfaces
2. INTERFACES intf.
Effect
This statement implements interfaces in classes or integrates interfaces into other interfaces. It can be used in the public visibility section of the declaration part of classes and in interface declarations.
Syntax
INTERFACES intf
[PARTIALLY IMPLEMENTED]
{ {[ABSTRACT METHODS meth1 meth2 ... ]
[FINAL METHODS meth1 meth2 ... ]}
| [ALL METHODS {ABSTRACT|FINAL}] }
[DATA VALUES attr1 = val1 attr2 = val2 ...].
Additions
1. ... ABSTRACT METHODS meth1 meth2 ...
2. ... FINAL METHODS meth1 meth2 ...
3. ... ALL METHODS {ABSTRACT|FINAL}
4. ... DATA VALUES attr1 = val1 attr2 = val2 ...
Effect
In the public visibility section, the statement INTERFACES implements the interface intf in the class. Additions can also be defined to determine the properties of interface components in the class.
Any local or global interfaces can be specified for intf here that are not already bound in a superclass of the current class. The components of the interfaces become public components of the class after the implementation. An interface component called comp has the name intf~comp in the class, where intf is the name of the interface and the character ~ is the interface component selector. A class must implement all methods of the interface in its implementation part, with the following exceptions:
◈ Interface methods declared as optional using the addition DEFAULT.
◈ Interface methods specified in the class after the addition ABSTRACT METHODS (making them abstract).
◈ Partial implementations are permitted in test classes using the addition PARTIALLY IMPLEMENTED.
Notes
◈ A class can implement any number of different interfaces. All of the interfaces implemented by a class are of equal status. If one of the interfaces intf implemented in a class is a composite (meaning it contains component interfaces), these are implemented in the class like individual interfaces, regardless of their nesting hierarchy, and their components are called using the name of their component interface instead of using the name intf. Multiple use of the interface component selection in a name (such as intf1~intf2~comp) is generally not supported.
◈ Each interface appears only once in a class and every interface component comp is always clearly accessible using the intf~comp. If the components of an interface appear to be implemented more than once in a class (since it is the interface component or one or more other interfaces), these components also exist only once.
◈ If the implementation of a non-optional method of a global interface implemented using INTERFACES is missing in a class, a syntax warning occurs instead of a syntax error. This prevents classes from becoming unusable when later enhancements are made to global interfaces. Calls of a missing implementation, however, always raise an exception of the class CX_SY_DYN_CALL_ILLEGAL_METHOD and produce the runtime error CALL_METHOD_NOT_IMPLEMENTED if the exception is not handled. A real syntax error is produced when local interfaces are used and the implementation is missing.
◈ If a class implements a method intf~... of a global interface intf implemented using INTERFACES in its implementation part and the method is not declared in the interface, a warning is displayed in the syntax check. This type of method implementation is dead code that cannot be executed and should be removed. Classes would become unusable after syntax errors if methods were later deleted from an implemented global interface and these methods are ignored by the class (for example, because they are implemented as empty methods). An actual syntax error results when local interfaces are used.
Addition 1
... ABSTRACT METHODS meth1 meth2 ...
Addition 2
... FINAL METHODS meth1 meth2 ...
Effect
Using the additions ABSTRACT METHODS and FINAL METHODS, the individual instance methods meth of the interface are made either abstract or final in the class to be implemented. The same rules apply as to the additions ABSTRACT and FINAL of the statement METHODS. In particular, the whole class must be abstract if an interface method is made abstract and no interface methods can be executed at the same time after ABSTRACT METHODS and FINAL METHODS.
Addition 3
... ALL METHODS {ABSTRACT|FINAL}
Effect
Instead of making individual interface methods in the class abstract or final it is possible, using the addition ALL METHODS {ABSTRACT|FINAL}, to make all interface methods either abstract or final.
Addition 4
... DATA VALUES attr1 = val1 attr2 = val2 ...
Effect
Using the addition DATA VALUES, initial values can be assigned to individual attributes attr. For instance attributes, this addition functions in the same way as the addition VALUE of the statement DATA for attributes in its own class. Constants declared in the interface by the statement CONSTANTS cannot be specified after the addition DATA VALUES. Furthermore, it is not currently possible to specify alias names.
Note
To specify values for the interface attributes of the component interfaces of a compound interface, the component interface must currently be directly bound again using the statement INTERFACES.
1.3 INTERFACES - integration
Syntax
INTERFACES intf.
Effect
In the declaration of an interface, the statement INTERFACES binds the interface intf in the declared interface. Additions cannot be specified. As a result, the interface intf becomes a component interface of a composite interface.
An interface can be composed of any number of different component interfaces. All these interfaces are equally valid and located at the same level. If a component interface itself is a composite (that is, it contains its own component interfaces), the nesting hierarchy is irrelevant for the composition of the interface. It is relevant, however, for accessing the interface components.
To access a component comp of a component interface intf within a composite interface, the expression intf~comp can be used with the interface component selector (~). Multiple use of the interface component selection in a name (such as intf1~intf2~comp) is generally not supported. In a composite interface, it is possible to use the interface component selector to access only interface components of the component interface that are bound in this interface using the statement INTERFACES. Since all nested interfaces are at the same level, however, all that is needed to access the interface components of all component interfaces is the name of their interface.
Notes
Each interface and its components appear only once in a composite interface. An interface that is seemingly implemented more than once in an interface (since it is an interface component of one or more other interfaces) also exists only once.
Since there are no separate namespaces for global and local interfaces, it must be ensured that compositions of local interfaces do not produce combinations of global and local interfaces with identical names, because they cannot be equally valid at the same level in their implementation.
Example
The following example demonstrates how the statement INTERFACES can be used to compose and implement interfaces. The class c1 implements the composite interfaces i2 and i3. Although i1 is a component interface of i2 and i3, it exists only once in class c1. A reference variable iref1 of the static type i1 is used to create an object class c1 and call method i1~m1, which is implemented there.
INTERFACE i1.
METHODS m1.
ENDINTERFACE.
INTERFACE i2.
INTERFACES i1.
METHODS m2.
ENDINTERFACE.
INTERFACE i3.
INTERFACES i1.
METHODS m3.
ENDINTERFACE.
CLASS c1 DEFINITION.
PUBLIC SECTION.
INTERFACES: i2, i3.
ENDCLASS.
CLASS c1 IMPLEMENTATION.
METHOD i1~m1.
...
ENDMETHOD.
METHOD i2~m2.
...
ENDMETHOD.
METHOD i3~m3.
...
ENDMETHOD.
ENDCLASS.
DATA iref1 TYPE REF TO i1.
START-OF-SELECTION.
CREATE OBJECT iref1 TYPE c1.
iref1->m1( ).
2. ALIASES
Syntax
ALIASES alias FOR intf~comp.
Effect
In the declaration part of a class or interface, this statement declares an alias name alias for a component comp of the interface intf. The naming conventions apply to the name alias. The interface intf must be implemented in the same class or included in the same interface. The alias name can be used instead of intf~comp in any position in which it is visible to access the interface component comp.
An alias name is a component of the class and the interface. It shares the namespace with the other components and is inherited by subclasses. In classes, an alias name can be declared in every visibility section.
Notes
Within a context, such as a class declaration or method, only one name should be used to access components. The syntax check issues a warning if both the alias name and the full name intf~meth are used together.
In particular, the alias name can be used when implementing interface methods in the implementation part of classes using METHOD and when redefining methods using METHODS ... REDEFINITION.
Example
In the interfaces i2, i3 and the class c1, declares alias names for the methods of the included or implemented interfaces. In the implementation part of the class, the interface methods in the METHODS statements are implemented using the interface component selector. The alias names of the classes can also be used here.
INTERFACE i1.
METHODS meth.
ENDINTERFACE.
INTERFACE i2.
INTERFACES i1.
ALIASES m1 FOR i1~meth.
METHODS meth.
ENDINTERFACE.
INTERFACE i3.
INTERFACES i2.
ALIASES: m1 FOR i2~m1,
m2 FOR i2~meth.
METHODS meth.
ENDINTERFACE.
CLASS c1 DEFINITION.
PUBLIC SECTION.
INTERFACES i3.
ALIASES: m1 FOR i3~m1,
m2 FOR i3~m2,
m3 FOR i3~meth.
ENDCLASS.
CLASS c1 IMPLEMENTATION.
METHOD i1~meth.
... m2( ) ...
ENDMETHOD.
METHOD i2~meth.
... m3( ) ...
ENDMETHOD.
METHOD i3~meth.
... m1( ) ....
ENDMETHOD.
ENDCLASS.
1.3 Field Symbols
Field symbols are placeholders or symbolic names for existing data objects (or parts of existing data objects), declared by the statement FIELD-SYMBOLS or by the declaration operator FIELD-SYMBOL. A memory area is assigned to a field symbol at program runtime. A field symbol does not reserve any physical space for a field, but is a type of dynamic label for a memory area hosting a particular data object (or part of the object). A field symbol can be used instead of data objects at operand positions of statements. When a statement of this type is executed, a memory area must be assigned to the field symbol by the statement ASSIGN or the addition ASSIGNING when processing internal tables.
Field symbols can point to almost any data object. A field symbol is the equivalent of a data reference variable dereferenced using ->*. Unlike data reference variables, value semantics are used to access a field symbol Accessing a field symbol is like accessing the named data object (or part of the object). For data reference variables, however, reference semantics apply.
1.3.1 FIELD-SYMBOLS
Syntax
FIELD-SYMBOLS <fs> { typing | obsolete_typing }.
Addition:
... typing
Effect
The statement FIELD-SYMBOLS declares a field symbol <fs>. The naming conventions apply to the name fs. The angle brackets of the field symbols distinguish them from data objects and are mandatory. Field symbols can be declared in any procedure and in the global declaration part of an ABAP program, but not in the declaration part of a class or an interface. A field symbol can be used in any operand position in which it is visible and which matches the typing defined using typing.
A field symbol is initial directly after its declaration (with the exception of obsolete typings without an explicit type), which means that it does not reference a memory area. A memory area must be assigned to it (normally using the statement ASSIGN) before it can be used as an operand. Otherwise an exception is raised.
Notes
◈ An inline declaration of field symbols can be made using the declaration operator FIELD-SYMBOL.
◈ The angle brackets are a part of the name, which means that a field symbol could potentially be called <> (but this is not recommended).
Addition
... typing
Effect
The addition typing is used to type the field symbol. The syntax of typing is described under Typing. The typing specifies which memory areas can be assigned to the field symbol and in which operand positions it can be used.
Note
Alongside the typings that use typing, an obsolete typing obsolete_typing is also possible (outside of methods).
Example
Types a field symbol <itab> as an internal table and a field symbol <wa> with a fully generic type.
FIELD-SYMBOLS: <itab> TYPE ANY TABLE,
<wa> TYPE any.
...
ASSIGN <itab>[ KEY primary_key ('...') = '...' ] TO <wa>.
2. Inline Declarations
An inline declaration is performed using a declaration operator in a declaration expression and is made in a declaration position. The result of the declaration is used in the current operand position, is visible statically from the current position, and is valid in the current context.
◈ Inline Declaration of Variables
◈ Inline Declaration of Field Symbols
Notes
Inline declarations are intended to make programs leaner and easier to understand. The following rules must also be observed:
◈ The rule that dictates no global variables and field symbols means that inline declarations should only be used in processing blocks that support local data.
◈ Inline declarations are an exception to the rule that local declarations should only be made at the start of a procedure. For this reason, they should only be used in easily manageable procedures, to make them easier to understand.
2.1 DATA - Inline Declaration
Syntax
... DATA(var) ...
Effect
A declaration expression with the declaration operator DATA declares a variable var used as an operand in the current writing position. The declared variable is visible statically in the program from the location DATA(var) and is valid in the current context. The declaration is made when the program is compiled, regardless of whether the statement is actually executed.
The declaration operator DATA can be specified in every compatible declaration position. The date type of the variable is determined by the operand type. It must be possible to derive this type statically in full.
A variable var declared inline cannot be used in a reading position of the same statement.
Notes
◈ A valid statement with an inline declaration of a variable can generally be interpreted as a short form for a declaration statement used as a direct prefix.
DATA var TYPE ...
... var ...
Exceptions to this rule occur only if an identically named data object from a more global context is used in the same statement. This field symbol is still valid and is only hidden after the statement.
◈ Just like the statement DATA, an inline declaration does not open a local context for the current statement block. An inline declaration for a variable can only be made once within a context and the variable cannot yet be declared there using DATA.
◈ An inline declaration cannot occur on the right-hand side of an assignment or within an expression.
◈ The operand position and the types of other operands can be included in the static derivation of the operand type. If the type of a different operand cannot be identified statically (perhaps because it is specified as a generically typed field symbol), either a suitable standard type is used or no inline declaration is possible.
◈ If the operand type is defined by reference to a data type in ABAP Dictionary, it is used together with its semantic attributes, such as field help, input help, or conversion routines.
◈ If more than one equally valid operand type is possible in the same declaration position, the recommended preferred data type is generally used.
Example
Inline declaration of an internal table as a target field of an assignment and inline declaration of an appropriate work area in a LOOP.
TYPES t_itab TYPE TABLE OF i
WITH NON-UNIQUE KEY table_line.
DATA(itab) = VALUE t_itab( ( 1 ) ( 2 ) ( 3 ) ).
LOOP AT itab INTO DATA(wa).
...
ENDLOOP.
2.2 FIELD-SYMBOL - Inline Declaration
Syntax
... FIELD-SYMBOL(<fs>) ...
Effect
A declaration expression with the declaration operator FIELD-SYMBOL declares a field symbol <fs> to which a memory area is assigned in the current operand position. The declared field symbol is visible statically in the program from FIELD-SYMBOL(<fs>) and is valid in the current context. The declaration is made when the program is compiled, regardless of whether the statement is actually executed.
The declaration operator FIELD-SYMBOL can be specified in every valid declaration position (this involves assignments of the memory area only). The typing of the field symbol is determined using the statically recognized type of the assigned memory area. It can be generic and complete.
A field symbol <fs> declared inline cannot be used in a reading position of the same statement.
Notes
◈ A valid statement with an inline declaration of a field symbol can generally be interpreted as a short form for a declaration statement used as a direct prefix.
FIELD-SYMBOLS <fs> TYPE ...
... <fs> ...
Exceptions to this rule occur only if an identically named field symbol from a more global context is used in the same statement. This field symbol is still valid and is only hidden after the statement.
◈ Just like the statement FIELD-SYMBOLS, an inline declaration does not open a local context for the current statement block. An inline declaration for a field symbol can only be made once within a context and the field symbol cannot yet be declared there using FIELD-SYMBOLS.
◈ If the type of the assigned memory area is defined by reference to a data type in ABAP Dictionary, it is used together with its semantic attributes, such as field help, input help, or conversion routines.
Example
Inline declaration of a field symbol for an internal table in an ASSIGN statement and inline declaration of a field symbol for the rows of the table in a LOOP.
TYPES t_itab TYPE TABLE OF i
WITH NON-UNIQUE KEY table_line.
DATA(dref) = NEW t_itab( ( 1 ) ( 2 ) ( 3 ) ).
ASSIGN dref->* TO FIELD-SYMBOL(<itab>).
LOOP AT <itab> ASSIGNING FIELD-SYMBOL(<line>).
...
ENDLOOP.
3. Local Declarations in Expressions
In certain expressions (currently only constructor expressions), variables and field symbols can be used as auxiliary fields within expressions. They are defined using the language element LET in a
LET expression.
3.1 let_exp - LET ... IN
Syntax
... LET {var1 = rhs1}|{<fs1> = wrexpr1}
{var2 = rhs2}|{<fs2> = wrexpr2} ... IN ...
Alternatives:
1. ... var = rhs ...
2. ... <fs> = wrexp ...
Effect
A LET expression defines variables var1, var2, ... or field symbols <fs1>, <fs2>, ... as local auxiliary fields in an expression and assigned values to them. When declared, the auxiliary fields can be used in the operand positions of the expression. There is no way of accessing an auxiliary field statically outside its expression. The documentation of an expression specifies whether it contains a LET expression and in which positions. Any LET expressions in an expression or subexpression are evaluated first.
An auxiliary field specified in a LET expression is valid in the context in which the LET expression is specified. This can be a full expression or just part of an expression. All auxiliary fields of a full expression are in the same namespace. A previously specified auxiliary field can be specified in a further LET expression of the same expression. Furthermore, the auxiliary fields are in the same namespace as the data objects or field symbols of the current procedure or program. Auxiliary fields cannot be defined in a LET expression if a data object or field symbol with the same name already exists in the procedure or program of the expression. Conversely, no data objects or field symbols with names given to auxiliary fields can be declared after an expression with a LET expression.
When reusing auxiliary fields in different expressions, the following applies:
◈ If an auxiliary field is defined for the first time in the current procedure or program, it is declared inline.
◈ If an auxiliary field in the current procedure or program is defined again in a LET expression in a different expression and the derived data type matches, the auxiliary field is bound to this expression and can be used there.
◈ If an auxiliary field in the current procedure or program is defined again in a LET expression in a different expression and the derived data type does not match, the auxiliary field cannot be used there and a syntax error occurs.
Notes
◈ LET expressions can currently only be used in constructor expressions. Subexpressions in which LET expressions can be used are iteration expressions with FOR and results specified after THEN and ELSE in the conditional expressions COND and SWITCH.
◈ In the assignment of a value operator VALUE to structures or internal tables, values from the left side can be saved to auxiliary fields using a LET expression before the left side is overwritten.
◈ An auxiliary field defined in a LET expression can be addressed dynamically in the entire current context. This is not recommended, however, since expressions are not supposed to produce side effects.
◈ It is a good idea to use LET expressions whenever auxiliary fields are required for performance reasons (by avoiding multiple calculations) or the readability of an expression or whenever values from the left side of an assignment in a VALUE operator are needed on the right side.
Example
Alternative 1
... var = rhs ...
Effect
Defines a local auxiliary variable var as an auxiliary field in a LET expression. The value of the right side, rhs, is assigned to the auxiliary variable as an initial value.
For the right side, rhs, the same can be specified as in a regular assignment using the assignment operator =. The data type of the auxiliary is determined from the right side, rhs, in exactly the same way as when an inline declaration DATA(var) is specified on the left side of an assignment operator using the assignment operator =. It must be possible to determine the data type in full from the right side to avoid syntax errors.
Notes
The auxiliary variables declared in a LET expression generally retain the value defined by rhs while the expression is being calculated. It is possible to modify the value of an auxiliary variable in the expression, for example by binding to a CHANGING parameter of a method, but this would be unusual.
The auxiliary variables declared in a LET expression are a good example of where long readable names are not necessary and can even harm readability. The auxiliary variables can only be used in their own expression, which means that short names (possibly even single-character names) are enough.
Example
Defines three local auxiliary variables, x, y, and z, in a constructor expression to construct the values of a structure. The values of the auxiliary variables are used for the structure components.
TYPES:
BEGIN OF struc,
col1 TYPE i,
col2 TYPE i,
END OF struc.
DATA(rnd) = cl_abap_random_int=>create(
seed = CONV i( sy-uzeit ) min = 1 max = 10 ).
DO 5 TIMES.
DATA(struc) = VALUE struc(
LET x = rnd->get_next( )
y = x * x
z = sy-index * 1000 IN col1 = x + z
col2 = y + z ).
cl_demo_output=>write( struc ).
ENDDO.
cl_demo_output=>display( ).
Alternative 2
... <fs> = wrexp ...
Effect
Defines a local field symbol <fs> as an auxiliary field in a LET expression. Here, the result of the writable expression wrexp is assigned to the field symbol. The same applies here as in assignments of writable expressions using ASSIGN, which means that only the expressions specified there can be used. The typing of the field symbol is determined by the type of wrexp and is performed in the same way as in inline declarations of a field symbol using the statement FIELD-SYMBOL.
Example
Defines a field symbol and a variable as auxiliary fields in a LET expression in a conversion expression. The rows of an internal table are assigned to the field symbol.
TYPES:
BEGIN OF date,
year TYPE c LENGTH 4,
month TYPE c LENGTH 2,
day TYPE c LENGTH 2,
END OF date,
dates TYPE TABLE OF date WITH EMPTY KEY.
DATA(dates) = VALUE dates(
( year = '2013' month = '07' day = '16' )
( year = '2014' month = '08' day = '31' )
( year = '2015' month = '09' day = '07' ) ).
DO lines( dates ) TIMES.
DATA(isodate) = CONV string(
LET <date> = dates[ sy-index ]
sep = '-'
IN <date>-year && sep && <date>-month && sep && <date>-day ).
cl_demo_output=>write( isodate ).
ENDDO.
cl_demo_output=>display( ).
LET Expression
This example demonstrates a LET expression in a constructor expression.
Source Code
REPORT demo_let_it_be.
CLASS demo DEFINITION.
PUBLIC SECTION.
CLASS-METHODS main.
ENDCLASS.
CLASS demo IMPLEMENTATION.
METHOD main.
TYPES text TYPE STANDARD TABLE OF string WITH EMPTY KEY.
cl_demo_output=>new( )->write(
VALUE text( LET it = `be` IN
( |To { it } is to do| )
( |To { it }, or not to { it }| )
( |To do is to { it }| )
( |Do { it } do { it } do| ) )
)->display( ).
ENDMETHOD.
ENDCLASS.
START-OF-SELECTION.
demo=>main( ).
Description
A constructor expression with the value operator VALUE constructs rows in an internal table. The value of the local auxiliary variable it is passed to the table.
4. Typing
Typing means defining a generic or complete data type for a formal parameter of a procedure or for a field symbol. When an actual parameter is assigned to a formal parameter, or a data object to a field symbol, a check is carried out to make sure the data type matches the typing.
Generically Typed
Unlike data objects, where the data type has a specific property and is always identified in full, formal parameters and field symbols that are generically typed receive their complete data type only when an actual parameter is passed in a procedure call or when a memory area is assigned using ASSIGN.
When using generically typed formal parameters or field symbols, a difference is made between static and dynamic access.
◈ In static access to a generically typed formal parameter, field symbol, or their components, the type attributes specified by the typing of the formal parameter are used. In static accesses where a complete data type is required, a standard type is used if possible.
◈ In static access to a generically typed formal parameter, field symbol ,or their components, the type attributes of the actual parameter are used.
The attributes of the actual parameter, which are not checked in calls or assignments, can be different from those of the formal parameter. This can produce different behavior in static and dynamic accesses. Dynamic access to components of generically typed formal parameters produces a runtime error, if the components are not available in the actual parameter.
Fully Typed
During compilation and at runtime, formal parameters and field symbols that are completely typed are handled in the same way as data objects with completely known data types.
During the use of completely typed formal parameters, or field symbols, the attributes specified by the typing are used, regardless of whether they are accessed statically or dynamically.
Notes
◈ The typing of formal parameters or field symbols defines some or all of the type attributes before the actual specification of the type. This permits the use of formal parameters and field symbols in operand positions that require certain type attributes.
◈ If the typing of an existing field symbol or formal parameter is made weaker, note that there may then be fewer options for static accesses and that the associated standard type may change if they are used in inline declarations.
◈ The static type of data reference variables is always completely generic (data) or completely typed
4.1 typing Addition
Syntax
... generic_type | complete_type ...
Effect
The addition typing is part of the definition of formal parameters and field symbols in the statements:
[CLASS-]METHODS
[CLASS-]EVENTS
FORM
FIELD-SYMBOLS
The addition allows a generic typing with generic_type and a complete typing with complete_type. In positions where the addition typing is not necessary, implicit typing with the generic type any takes place (if no typing is specified explicitly).
Notes
◈ In classes, the formal parameters of methods or events and field symbols must be typed explicitly. The formal parameters of methods or events of global classes and the formal parameters of function modules are typed in Class Builder or Function Builder. For a typing of system wide visible public interface parameters to be carried out in Function Builder or Class Builder, only the types in ABAP Dictionary may be used.
4.1.1 typing Addition - generic_type
Syntax
... { TYPE generic_type }
| { LIKE <generic_fs>|generic_para } ...
Effect
To generically type a formal parameter or a field symbol,
◈ specify any generic ABAP type generic_type (except object) after TYPE.
◈ specify a field symbol visible at this position (<generic_fs>) or a formal parameter (generic_para) with generic typing, after LIKE. The typing defined is applied when the field symbol/parameter is declared. In method parameters, all generic typings are possible. No complete generic typings are possible in parameters of subroutines and field symbols.
When an actual parameter or memory area is assigned to a generically typed formal parameter or field symbol, the system checks whether the specified data type is a subset of the generic type.
The formal parameter or field symbol can be used as operands anywhere that is not excluded by this typing. However, operand positions that expect internal tables are an exception to this rule. Here, only formal parameters or field symbols (as internal tables) with the appropriate table category are allowed.
The type attributes specified by the typing are used in static access to a generically typed formal parameter or field symbol. In dynamic access, the attributes of the actual parameter or memory area assigned apply.
If an actual parameter is not specified for a generically typed optional formal parameter of a method or a function module when calling the procedure and no replacement parameter is defined in the procedure, the formal parameter is typed with a standard type in accordance with the following rules:
◈ any and data are converted to the type c with length 4.
◈ c, clike, csequence, and simple are converted to the type c with length 1.
◈ n is converted to the type n with length 1.
◈ numeric and p are converted to the type p with length 8 without decimal places.
◈ x and xsequence are converted to the type x with length 1.
◈ ANY TABLE and INDEX TABLE are converted to STANDARD TABLE.
◈ For ANY TABLE, INDEX TABLE, [STANDARD] TABLE SORTED TABLE, and HASHED TABLE, the row type is set to c with length 1.
◈ For generic table types without specification of a primary table key, the standard key is completed for standard tables and the entire table row (without any table-like parts) is completed as the key specification for sorted tables and hashed tables.
◈ For generic table types, for which the primary table key is specified but uniqueness is not specified, the standard key is set to non-unique for standard tables and sorted tables, and to unique for hashed tables.
◈ This generic property is ignored for table types that are generic with respect to the secondary table key. This applies even if the generic property was defined explicitly with the addition WITH FURTHER SECONDARY KEYS.
If a replacement parameter is specified, the type attributes of this parameter are applied.
Note
When formal parameters are typed, the addition LIKE can be used to reference formal parameters (in the same procedure) that have already been declared.
Example
In the following example, two generically typed field symbols are used in LOOP statement. To avoid syntax errors, <any_table> must be defined as an internal table. However, the system does not check the type of <any_object> until runtime, to ensure that the type of the data object assigned to it is compatible with the row type of the table.
FIELD-SYMBOLS: <any_object> TYPE ANY,
<any_table> TYPE ANY TABLE.
...
LOOP AT <any_table> INTO <any_object>.
...
ENDLOOP.
4.1.2 typing - Addition - complete_type
Syntax
... { TYPE {[LINE OF] complete_type}
| {REF TO type} }
| { LIKE {[LINE OF] dobj}
| {REF TO dobj} } ...
Effect
The following methods are available for typing a formal parameter or a field symbol completely:
◈ Specify any non-generic type (complete_type) after TYPE. complete_type can be a non-generic data type from ABAP Dictionary, a non-generic public data type from a global class, a non-generic program-local type already defined using TYPES<, or a non-generic predefined ABAP type.
◈ Specify a data object dobj after LIKE. dobj is specified based on the rules TYPES ... LIKE. The bound type of the data object is applied. If field symbols and formal parameters are specified for dobj, they must be completely typed, to make sure that typing is performed in full.
If complete_type or the data type of dobj is table-like, LINE OF can be used to reference the appropriate row type.
REF TO types the formal parameter or field symbol as a reference variable. In this case, the same rules apply as for the definition of reference types in TYPES. Typings with TYPE REF TO data or TYPE REF TO object are also considered as complete typings.
If an actual parameter or a memory area is assigned to completely typed formal parameters or field symbols, the technical attributes of the specified data type must match the typing exactly (more information: Typing Check), except when passing literals. Completely typed formal parameters and field symbols can be used in the same operand positions as data objects of the corresponding data type.
Type attributes specified by the typing are used during both static and dynamic access to a fully typed formal parameter or field symbol.
Notes
◈ The data types of the ABAP Dictionary that can be referred to with TYPE especially include the CDS entities (CDS views, CDS table functions).
◈ LIKE can be used to refer to data objects, and also to the public attributes of global classes.
◈ When formal parameters are typed, the addition LIKE can be used to reference formal parameters (in the same procedure) that have already been declared.
◈ Outside classes, LIKE can also be used for an obsolete type reference.
◈ The predefined generic data type any cannot currently be specified after REF TO.
Example
In the following example, the field symbol <spfli> is completely typed with structured data type spfli from the ABAP Dictionary, and can therefore be used like a structure of that data type.
FIELD-SYMBOLS <spfli> TYPE spfli.
...
<spfli>-carrid = ...
4.2 Checking Typing
When data objects are assigned to typed field symbols and when actual parameters are assigned to typed formal parameters of procedures, the system checks whether the data type of the assigned data object matches the typing of the field symbol or of the formal parameter.
◈ General Rules for Typing
Special rules apply to:
◈ Return Values of Functional Methods
◈ Literals as Actual Parameters
◈ Functions and Expressions as Actual Parameters
Note
When specifying data objects suitable for a typing, an assignment to a helper variable with a valid data type is often made. When methods are called, these types of helper variables can often be skipped by using a constructor expression in the position of an actual parameter.
4.2.1 General Rules for Typing
The general rules for checking apply strictly to the following:
◈ The assignment of all data objects to field symbols
◈ The linking of the said data objects to input, input/output, and output parameters for procedures
The general rules for checking the typing are:
◈ If the assignment is made to generically typed field symbols or field parameters, the system checks whether the technical type attributes of the assigned data object are a subset of the generic type. The type attributes that are not defined by typing are applied to the actual parameter.
◈ If the assignment is made to fully typed field symbols or formal parameters, the technical attributes of the data type of the assigned data object must correspond exactly to the typing.
◈ The result of the typing check when actual parameters are passed to formal parameters is independent of the passing type used. In a pass by value, the check for pass by reference is always carried out, even though this is stricter than necessary in individual cases.
◈ If reference variables are passed, up casts are possible but down casts are not. If actual parameters are passed to input parameters typed as reference variables, an up cast is only possible if there is no change of content within the procedure. When a subroutine is passed to the parameters, an up cast is not possible.
◈ If memory areas are assigned to field symbols typed as reference variables, the typing of the field symbol and the static type of the memory area must be the same.
◈ If the assignment is made to generically and fully typed field symbols or formal parameters, only the technical type attributes are checked. The following are not checked:
◈ Names of structure components (names of nodes and associations of meshes are possible here).
◈ Semantic attributes of data types defined in ABAP Dictionary (conversion routines, documentation, and so on)
◈ Initial memory requirement of internal tables
If generally typed formal parameters or field symbols are accessed dynamically, these attributes are applied to the type of the actual parameter. If generically typed formal parameters or field symbols are accessed statically, these attributes are applied to the typing of the formal parameter.
◈ When assigning to field symbols or formal parameters for which a structure is defined with the obsolete STRUCTURE addition are called in Unicode programs, elementary data structures must be character type and flat and for structures the fragment views must match.
Notes
◈ In the case of generically typed field symbols or formal parameters, and in the case of formal parameters of function modules and externally called subroutines, the typing is checked first at the time of the assignment - that is, at runtime. In the case of fully typed field symbols and formal parameters of methods and internally called subroutines, the check is performed as part of the syntax check.
◈ The constructor operators CONV and CAST are well suited to converting or casting invalid actual parameters to the type of a formal parameter.
4.2.2 Return Values of Functional Methods
The return value of a functional method is always fully typed and always passed on as a value. An actual parameter can be appended to the return value as follows:
◈ Method call with the addition RECEIVING
If an actual parameter is specified explicitly after RECEIVING, this does not have to comply with the general typing rules for typing the formal parameter; instead, it is enough if the formal parameter can be converted to the actual parameter in accordance with the conversion rules.
◈ Specification of the method at an operand position
If a function method is used at an operation position, the return value is used like a data object whose data type is determined by the full typing of the return value (a type-compatible actual parameter is implicitly associated with it). Checking of this typing is not necessary (or is always successful). An error always occurs, however, if the typing of the return value does not match the operand type.
Note
If reference variables are returned using RECEIVING, an up cast is possible, but a down cast is not.
4.2.3 Literals as Actual Parameters
Special rules apply to the assignment of literals to formal parameters. They make it possible to assign character literals of type c and string or numeric literals of type i and p to formal parameters whose type would not normally allow it.
If the formal parameter has a generic type, the non-specified type attributes are defined by the contents of the specified literal (see table 1). When a literal is bound, the pass is always executed as a pass by value, even if pass by reference is defined for the formal parameter.
If a literal meets the type requirements of the parameter, its contents are assigned to the formal parameter according to the relevant conversion rules for elementary data types. However, in contrast to the normal application of these rules, a non-catchable exception is raised if the value range of the target is exceeded.
Checking Character Literals
Table 1 shows the requirements that a character literal must meet to be assigned to a formal parameter. These rules apply to both text field literals and text string literals.
Table 1
Typing | Requirement |
c | If the formal parameter has a fixed length, the length of the literal may not exceed this length. If the length is generic, the formal parameter inherits the length of the literal. |
d | The literal must be eight characters long. |
decfloat, decfloat16, decfloat34 | The literal must contain a number in mathematical, commercial, or scientific notation. If generic typing with decfloat is used, the formal parameter contains the data type decfloat34. |
f | The literal must contain a number in scientific notation . |
i, int8, (b, s) | The literal must contain a number in mathematical or commercial notation. The literal must not contain any decimal places. |
n | The literal may only contain digits. If the formal parameter has a fixed length, the length of the literal may not exceed this length. If the length is generic, the formal parameter inherits the length of the literal. |
numeric | The literal must contain a number in mathematical or commercial notation. The formal parameter inherits the data type p, length 16, and the decimal spaces specified in the literal. |
p | The literal must contain a number in mathematical or commercial notation. If a generic formal parameter is used, the length is set to 16. The number of decimal spaces is set to the number of spaces specified in the literal. If the program attribute Fixed Point Arithmetic is activated in the called procedure, the number of decimal places in the literal for a completely typed formal parameter must be less than or equal to the number of decimal places in the formal parameter. If the attribute Fixed Point Arithmetic is deactivated in the called procedure, the number in the literal must have exactly the same number of decimal places as the formal parameter. |
string | The literal can have any length. |
t | The literal must be six characters long. |
x | The literal may only contain valid hexadecimal characters, that is the digits "0" to "9" and the letters "A" to "F". If the formal parameter has a fixed length, the length of the literal may not be more than twice this length. If the length is generic, the number of bytes specified in the literal determines the length of the formal parameter. |
xstring | The literal may only contain valid hexadecimal characters, that is the digits "0" to "9" and the letters "A" to "F". |
xsequence | The literal may only contain valid hexadecimal characters, that is the digits "0" to "9" and the letters "A" to "F". |
All other types have the same requirements of character literals as apply to other actual parameters. Generic formal parameters inherit the type of the actual parameter. With the exception of formal parameters listed in table 1, character literals can only be passed to formal parameters with types c or string.
Note
Character literals that are passed to actual parameters can be joined using the literal operator &. The rules described above apply here. However, if a join with the chaining operator && is used, the actual parameter is a string expression of type string and the formal parameter must be typed accordingly.
Checking Numeric Literals
Table 2 shows the requirements for numeric literals that are to be passed to typed formal parameters.
Table 2
Typing | Requirement |
f | All numeric literals are allowed. |
decfloat, decfloat16, decfloat34 | All numeric literals are allowed. If generic typing with decfloat is used, the formal parameter contains the data type decfloat34. |
i, int8, (b, s) | All numeric literals are allowed. |
n | The value of the literal must not be negative. If the formal parameter has a fixed length, the number of digits may not exceed this length. If the formal parameter is generic, its length is set to 10, if the literal has the data type i; its length is set to 31 if the literal has the data type p. |
p | If a generic formal parameter is used, the length is set to 16 and the number of decimal spaces is set to 0. If the program attribute Fixed Point Arithmetic is deactivated, the formal parameter cannot have any decimal places or the literal must have the value 0. |
All other types make the same requirements on numeric literals as on other actual parameters. Generic formal parameters inherit the type of the actual parameters. With the exception of formal parameters of the types listed in table 2, numeric literals can only be passed to formal parameters with data types i or p.
Functions and expressions can be specified as actual parameters in the following formal parameters:
◈ Writing positions
Output parameters, input/output parameter, and return value in method calls.
◈ Reading positions
Input parameters of methods in method calls, when objects are created, or when exceptions are raised using RAISE EXCEPTION or THROW in a condition exception
Input parameters of function modules in all variants of the statement CALL FUNCTION.
The parameters are read from left to right (and from inside to outside) and the procedure executed. A parameter cannot be modified by the method itself or by the evaluation of a preceding expression. This applies in particular to writable expressions in result positions.
Special rules apply to typing checks, identifying the calculation type, and parameter passes.
- Checking Typing
- Calculation Type and Calculation Length
- Passing Parameters
- Fully Typed
- Generically Typed
Note
In the case of dynamic method calls, the same rules apply as to static method calls. However, the handling during runtime is time-consuming. Therefore, helper variables should be used in a dynamic call instead of functions or arithmetic expressions if possible. Function module calls are always dynamic and, compared to method calls, fewer rules apply.
Checking Typing
- A numeric function, a description function, or an arithmetic expression can
- be bound to any numerically typed input parameter in a method call.
- be bound to any appropriately typed input parameter in a function module call.
- A bit function or a bit expression can
- be bound to any byte-like typed input parameter in a method call.
- be passed to input parameters of the type x or a generic type covering x in function module calls.
- A string function or a string expression can
- be bound to any character-like typed input parameter in a method call.
- be passed to input parameters of the type string or a generic type covering string in function module calls.
- A constructor expression can
- be passed to every input parameter that matches the specified type type of the constructor expression in method calls. In this case, the # character can only be specified for type if the input parameter is typed in full and this type is used.
- be used in function module calls if the function module matches the specified type type of the constructor expression. The character # cannot be specified for type ion the constructor expression since static derivations of types are not possible in function module calls.
- A table expression can
- be passed in method calls or function calls to every input parameter that matches the type of the result
Note
In function module calls, the typing is not checked until runtime.
Calculation Type and Calculation Length
◈ The calculation type of an arithmetic expression is determined
◈ in method calls from the operands of the expression and the typing of the input parameter, if this parameter is fully typed. If the input parameter is typed generically, only the operands of the expression are evaluated.
◈ in function module calls from the operands of the expression. The typing of the input parameter is ignored.
◈ The calculation length of a bit expression is the length of the largest operand of the expression.
Passing Parameters
When binding a function, a calculation expression, a constructor expression, or a table expression, the parameters are always passed by value, even if the formal parameter is defined as to be passed by reference.
Fully Typed
The return value of a function or the result of a calculation expression, a constructor expression, or a table expression is converted, if necessary, to the type of the input parameter and passed.
Generically Typed
◈ In a function, a constructor expression, or a table expression, the formal parameter inherits the type of the return value or result. Only bit functions are handled like bit expressions (see below).
◈ With an arithmetic expression, the formal parameter takes over the calculation type determined by the operand. If the calculation type is p, the number of decimal places is determined by the accuracy required by the calculation and therefore depends on the values of the operands.
◈ In a bit expression or a bit function, the formal parameter is set to type x in the calculation length determined by the operands.
◈ In a string expression, the formal parameter is set to the type string in the case of fully generic typing or the generic types csquence clike. In the case of the types c and n with generic lengths, the length is set to the length of the result of the string expression.
Example
The functional method m1 is called twice for each assignment to result. The first call is executed in an arithmetic expression, which is passed as an actual parameter in the second call. In the first call of each assignment, the formal parameter p1 has type p of length 16. The number of decimal places is 0 in the first assignment, 14 in the second, and 1 in the third assignment. In the second call, the formal parameter p1 has the type decfloat34 in each assignment, because the calculation type of the arithmetic expression is determined by the return value of m1.
CLASS c1 DEFINITION.
PUBLIC SECTION.
CLASS-METHODS m1 IMPORTING p1 TYPE numeric
RETURNING value(ret) TYPE decfloat34.
ENDCLASS.
CLASS c1 IMPLEMENTATION.
METHOD m1.
ret = p1.
ENDMETHOD.
ENDCLASS.
DATA num1 TYPE p DECIMALS 2 VALUE '2.00'.
DATA num2 TYPE p DECIMALS 2 VALUE '1.00'.
DATA result TYPE decfloat34.
START-OF-SELECTION.
result = c1=>m1( sqrt( 4 ) + c1=>m1( num1 / 2 ) ).
result = c1=>m1( sqrt( 4 ) + c1=>m1( num1 / 3 ) ).
result = c1=>m1( sqrt( 4 ) + c1=>m1( num2 / 2 ) ).
4.3 Generic and Complete Typing
The example shows how to access generically and completely typed formal parameters.
Source Code
REPORT demo_typing.
CLASS demo_typing DEFINITION.
PUBLIC SECTION.
CLASS-METHODS start.
PRIVATE SECTION.
TYPES: BEGIN OF struc1,
cola TYPE i,
colb TYPE i,
END OF struc1,
BEGIN OF struc2,
colb TYPE i,
cola TYPE i,
END OF struc2,
itab1g TYPE STANDARD TABLE OF struc1,
itab2g TYPE STANDARD TABLE OF struc2,
itab2c TYPE STANDARD TABLE OF struc2
WITH NON-UNIQUE DEFAULT KEY.
CLASS-METHODS sort_itab IMPORTING VALUE(pg) TYPE itab2g
VALUE(pc) TYPE itab2c.
ENDCLASS.
CLASS demo_typing IMPLEMENTATION.
METHOD start.
DATA: tab TYPE itab1g,
wa LIKE LINE OF tab.
tab = VALUE #(
FOR j = 1 UNTIL j > 5
( cola = j colb = 6 - j ) ).
sort_itab( pg = tab
pc = tab ).
ENDMETHOD.
METHOD sort_itab.
DATA(out) = cl_demo_output=>new( ).
SORT pg BY cola.
out->write_data( pg ).
SORT pg BY ('COLA').
out->write_data( pg ).
SORT pc BY cola.
out->write_data( pc ).
SORT pc BY ('COLA').
out->write_data( pc ).
out->display( ).
ENDMETHOD.
ENDCLASS.
START-OF-SELECTION.
demo_typing=>start( ).
Description
In the class demo_typing, three table types are declared:
itab1g has the line type struc1 with the components cola and colb. It is generic since the primary table key has not been specified.
itab2g has the line type struc2 with the components colb and cola. It is generic since the primary table key has not been specified.
itab2c has the line type struc2 with the components cola and colb. It is complete since the primary table key has been specified.
The method sort_itab has two formal parameters:
pg is typed generically with itab2g.
pc is typed completely with itab2c.
In the method start, an internal table tab is declared by referring to itab1g. The key is specified implicitly. This table is filled and passed to the formal parameters of sort_itab.
In sort_itab, both formal parameters are sorted twice. In the first sort, the column cola is specified statically as a sort criterion, in the second sort, it is specified dynamically. The behaviour is as follows:
The first SORT statement statically accesses the generically typed formal parameter pg. In this case, the typing with itab2g takes priority in which cola is the second column.
The second SORT statement dynamically accesses the generically typed formal parameter pg. In this case, the type of the actual parameter itab1g takes priority in which cola is the first colulmn.
The third and fourth SORT statements dynamically or statically access the completely typed formal parameter pc. In these cases, the typing with itab2c takes priority in which cola is the second column.
If components of generically typed formal parameters are accessed dynamically, a runtime error may occur if the components do not exist in the actual parameter.
No comments:
Post a Comment