Tuesday, June 23, 2009

Lists in Unicode Systems

A WRITE statement writes the content of data objects to a list. When you write using a WRITE statement, the output is stored in the list buffer and is displayed from there when the list is accessed.

Each time a data object is output with WRITE, the system determines an output length either implicitly or explicitly; the implicit output length depends on the data type. The output length defines the following two attributes:

  • Number of positions or storage spaces available for characters in the list buffer
  • Number of columns or cells available in the actual list

If the output length is shorter than the length of the data object, the system shortens its content according to certain rules when writing the data to the list buffer. Any values lost in numeric fields are indicated by a *.

When a list is displayed or printed, the contents stored in the list buffer are transferred to the list as follows:

  • In non-Unicode systems, each character occupies the same amount of space in the list buffer as it requires columns in the list. In single-byte systems, a character requires one byte in the list buffer and one column in the list, while a character that occupies several bytes in the list buffer in a multi-byte system also occupies the same number of columns in the list. For this reason, all characters stored in the list buffer are displayed in the list in non-Unicode systems.
  • In Unicode systems, each character usually requires one position in the list buffer. However, a character can also occupy more than one column, as is the case for Eastern Asian characters. However, since the list only contains the same number of columns as there are positions in the list buffer, the number of characters that can be displayed in the list is smaller than the number of characters stored in the list buffer in this case. List output is shortened accordingly, with the page formatted according to the specified alignment and marked with the characters > or <. You can then only display the entire content of the list by choosing the menu path System → List → Unicode Display.

For this reason, the horizontal position of the list cursor only has the same meaning as the output column in a list displayed or printed in non-Unicode systems. In Unicode systems, this is only guaranteed for the top and bottom output limits.

Rules for WRITE Statements

To avoid cutting off values unintentionally as far as possible, the rules for WRITE statements in Unicode programs have been modified and extended.

Operands in the WRITE statement

If the data object specified in WRITE is a

flat structure, this must only be character-type in Unicode programs.

Note

This also applies for the statement WRITE TO, in which the target field must also be character-type.

WRITE Statements with Implicit Output Length

In Unicode programs, WRITE statements without an explicitly specified output length for all data objects with the exception of text field literals and data objects of the type string behave in the same way as in non-Unicode programs. This means fewer characters may be displayed in the list than are stored in the list buffer.

In the case of text field literals and data objects of the type string, the system assumes that all characters are to be displayed. For this reason, the implicit output length is calculated according to the characters in the data object in such a way that it corresponds to the number of columns required in the list. If this output length is greater than the length of the data object, superfluous positions are filled with blanks when the data is written to the list buffer. When displaying the data in the list, the system removes these blanks, since the character representation fills the output length exactly.

WRITE Statements with Explicit Output Length

If a numeric data object is specified as an explicit output length after the AT addition for a WRITE statement, the value of this number is used as the output length, both in Unicode and non-Unicode systems. In Unicode systems, the number of characters displayed in the list can differ from the number of characters stored in the list buffer. You can specify the output length in the following way instead of using numeric data objects:

  1. WRITE AT (*) ...
    1. In data objects of the types c and string, the output length is set to the number of columns required to display the entire content in the list; closing blanks are not taken into account for type c. In the case of data objects of the type string, this has the same meaning as the implicit length.
    2. In data objects of types d and t, the output length is set to 10 and 8.
    3. In data objects of the numeric types i, f, and p, the output length is set to the value required to display the current value including thousand separators. This rule is applied to the value after any CURRENCY, DECIMALS, NO-SIGN, ROUND, or UNIT have been used.
    4. The implicit output length is used for data objects of the types n, x, and xstring.

  2. WRITE AT (**) ...
    1. In data objects of the type c, the output length is set to twice the length of the data object, and in data objects of the type string, to twice the number of characters contained in the object.
    2. In data objects of the types d and t, the output length is set to 10 and 8.
    3. In data objects of the numeric types i, f, and p, the output length is set to the value required in order to display the maximum possible values for these types, including plus and minus signs and thousand separators. This rule is applied to the value after any CURRENCY, DECIMALS, NO-SIGN, ROUND, or UNIT additions have been used.
    4. The implicit output length is used for data objects of the types n, x, and xstring.

The behavior of the output lengths (*) and (**) when using the addition USING EDIT MASK and the templates for date fields is described in Formatting Options.



Additions for GET/SET CURSOR FIELD/LINE

The additions DISPLAY OFFSET and MEMORY OFFSETtake account of the fact that data objects can occupy different lengths when displayed in a list and when stored temporarily in the list buffer.

In accordance with this fact, the addition DISPLAY OFFSET off positions the cursor in the column in the output area specified in off for the SET CURSOR { FIELD f | LINE l } statement. The addition MEMORY OFFSET off positions the cursor on the character in the output area that is located in the position (of the data object in f) in the list buffer specified in off.

In the same way, a GET CURSOR { FIELD f | LINE l } statement used with the addition DISPLAY OFFSET off places the cursor position in the output area in the data object off. When you use the addition MEMORY OFFSET off, the cursor position in the list buffer that is assigned to the character displayed is placed in the data object off. The addition DISPLAY is the standard setting and can therefore be ignored.



Class for Formatting Lists

Class CL_ABAP_LIST_UTILITIES has been introduced to calculate output lengths, convert values from the list buffer, and define field limits. The return values of the methods of this class can be used to program a correct column alignment in ABAP lists, even for output of Eastern Asian characters.



List Settings

The objects in a list can be displayed in different output lengths by specifying the desired length in the menu under System → List → Unicode Display. This is particularly advantageous for screen lists in Unicode systems where the output is cut off as indicated by the characters > or <.



Recommendations

We recommend that you adhere to the following rules when programming lists, to ensure that they have the same appearance and functions both in Unicode and non-Unicode systems:

  • Specify an adequate output length
  • Do not overwrite parts of a field
  • Do not use the additions RIGHT-JUSTIFIED or CENTERED for WRITE TO if this statement is followed by list output with WRITE.
  • In customer-programmed horizontal scrolling with a SCROLL statement, you should only specify the upper or lower limit of data objects displayed, since the positions in the list buffer and in the list displayed are only certain to match for these field limits in Unicode systems.

The File Interface in Unicode Programs

Since the content of files frequently reflects the structure of data in the working memory, the file interface in a Unicode system must fulfill the following requirements:

  • It must be possible to exchange data between Unicode and non-Unicode systems.
  • It must be possible to exchange data between different Unicode systems.
  • It must be possible to exchange data between different non-Unicode systems that use different code pages.

For this reason, in Unicode programs, you must always define the code page used to encode the character-type data that is written in text files or that is read from text files.

You must also consider that a Unicode program must be executable in a non-Unicode system as well as a Unicode system. Some of the syntax rules for the file interface have therefore been modified so that programming data access in Unicode programs is less prone to errors than in non-Unicode programs.

  • Before every read or write access, a file must be opened explicitly using OPEN DATASET. Furthermore, a file that is already open cannot be opened again. In non-Unicode programs, the first time a file is accessed, it is implicitly opened using the standard settings. The statement for opening a file can be applied to an open file in non-Unicode-programs, although a file can only be opened once within a program.
  • When opening the file, the access type and type of file storage must be specified explicitly using the following additions:
  • INPUT|OUTPUT|APPENDING|UPDATE
  • [LEGACY] BINARY|TEXT MODE
When opening a file in TEXT MODE, the ENCODING addition must be used to specify the character representation. When opening a file in LEGACY MODE, the byte order (endian) and a non-Unicode code page must be specified.
In non-Unicode programs, if nothing is entered, a file is opened with implicit standard settings.
  • If a file is opened for reading, the content can only be read. In non-Unicode programs, it is also possible to gain write access to these files.
  • If a file is opened as a text file, only the content of character-type data objects can be read or written. In non-Unicode programs, byte-type and numeric data objects are also allowed.

Note

In Unicode programs, file names can also contain blank characters.



Character String and Byte String Processing in Unicode Programs

In Unicode programs, character string and byte string processing are strictly separated. The operands of character string processing must be character-like data objects, and operands in byte string processing must be byte-like data objects. In non-Unicode programs, byte strings are normally handled in the same way as character strings.

Syntactic separation

Statements for character string and byte string processing

In the statements for character string and byte string processing, in Unicode programs, the distinction is made in the statements that are intended for both types of processing by the optional addition IN CHARACTER|BYTE MODE. In this case, IN CHARACTER MODE is the default.

Note

The addition IN CHARACTER|BYTE MODE is also used in the statements for determining length and offset:

  • DESCRIBE FIELD ... LENGTH
  • DESCRIBE DISTANCE

In this case, the specifications are obligatory

Relational operators for character strings and byte strings

There are relational operators for character strings and for byte strings. In Unicode programs, the latter can no longer be used for byte strings.

Functions for character strings and byte strings

The description functions are divided into description functions for character strings and description functions for byte strings. In particular, in Unicode programs, strlen can now only be used for character-like arguments, while xstrlen is available for byte-like arguments.

Structure Enhancements and Unicode Programs

Since Release 3.0, the ABAP Dictionary structures and database tables that are delivered by SAP can be subsequently enhanced with Customizing-Includes or append structures. Such changes cause problems in unicode programs if the enhancement changes the unicode fragment view.

For this reason, the option to classify structures and database tables was introduced, which makes it possible to recognize and handle problems related to structure enhancements. This classification is used during the program check to create a warning at all points where it works with structures, and where later structure enhancements can cause syntax errors or changes in program behavior. When you define a structure or a database table in the ABAP Dictionary, you can specify the enhancement categories that are displayed in the following table as classification.

Level Category Meaning
1 Not classified The structure does not have an enhancement category.
2 Cannot be enhanced The structure may not be enhanced.
3 Can be enhanced and character-type All structure components and their enhancements have to be character-type flat.
4 Can be enhanced and character-type or numeric. All structure components and their enhancements have to be flat.
5 Any enhancements All structure components and their enhancements can have any data type.

The warnings displayed after the program check - depending on the effects of the structure enhancements that are permitted - are classified into three levels from the following table.

Level Type of Check Meaning
A Syntax check An enhancement that fully utilizes the enhancement category of the relevant structure. It leads to a syntax error.
B Extended check Permitted enhancements can, but do not always have to, result in a syntax error.
C Extended check Permitted enhancements cannot result in syntax errors, although changes to program behavior do result in semantic problems.

Example

If the structure ddic_struc in the ABAP Dictionary is defined only with flat components but is classified as Any enhancements, then the following program section leads to a warning during the syntax check. If the structure were enhanced by a deep component after the program was delivered, the program would be syntactically incorrect and no longer executable. This is why in this case you either have to classify the structure ddic_struc in the ABAP Dictionary as Can be enhanced and character-type or else you cannot specify the offset/length in the program.

DATA: my_struc TYPE ddic_struc,
str TYPE string,
off TYPE i,
len TYPE i.
...
str = my_struc+off(len).

Structure Typing in Unicode Programs

For downward compatibility reasons, a structure can still be cast for field symbols and parameters of function modules and subroutines using the obsolete addition STRUCTURE.

When assigning a data object to such a field symbol or passing an actual parameter to such a formal parameter, in non-Unicode programs, the system only checks whether the length of the data object or actual parameter has at least the length of the structure and whether the alignment is identical at runtime. Unicode programs make a difference between structured and elementary data objects or actual parameters. For a structured data object or actual parameter, its Unicode fragment view must match the cast structure including all alignment gaps (including the closing ones). In addition, an elementary data object or actual parameter must be character-type and flat.

When a formal parameter of a function module is typed with a flat structure using LIKE instead of TYPE, LIKE has the same effect as STRUCTURE. However, the system checks the exact length during the parameter transfer in non-Unicode programs.

Note

The check of the Unicode fragment view can avoid problems that occur in non-Unicode systems due to closing alignment gaps. Example: The filliing of actual parameters with the content of an alignment gap which is not type-specific.

Conversion of Structures in Unicode Programs

The most important differences between the behaviors of Unicode programs and non-Unicode programs are the changed conversion rules for structures for assignments and for comparisons.

Note

Two structures in Unicode programs are only compatible when all alignment gaps are identical on all platforms. This applies in particular for alignment gaps that are created by included structures (INCLUDE)

Assignments between flat structures

In non-Unicode programs, incompatible flat structures are treated as data objects of the type c, whereas in Unicode programs, conversion rules apply which assign the most important role to the Unicode fragment view of the structures.

Assignments between flat structures and single fields

In non-Unicode programs, flat structures are treated as data objects of the type c in case of the assignment of elementary data objects and the assignment to elementary data objects, whereas in Unicode programs, aconversion rule applies according to which the structure must be character-type either completely or at least in the initial fragment.

Comparisons between incompatible flat structures

As is the case with the assignment, the structures are not treated as c fields, but according to their Unicode fragment view (see comparison rules between operands).

Comparisons between flat structures and single fields

As is the case with the assignment, the system checks whether the structure is character-type either completely or at least in the initial fragment (see Comparison Operators for All Data Types).

Access to memory sequences in Unicode programs

The following (in some cases obsolete) statements access data objects that are stored in the memory as an equally spaced sequence:

  • DO ... VARYING
  • WHILE ... VARY
  • ADD ... THEN ... UNTIL
  • ADD ... FROM ... TO

In the DO and WHILE loops in Unicode programs, all data objects of the sequence must be compatible and either be structure components that belong to the same structure, or subareas of the same data object specified using offset/length specifications. In Unicode programs, a RANGE must also be entered if it cannot be statically recognized that the data objects involved are components of the same structure. Otherwise, the permitted memory area is determined from the smallest possible substructure.

When memory sequences are added using ADD, in Unicode programs, all data objects of the sequence must be components of a structure. If this cannot be statically recognized in the syntax check, a structure must be specified using the addition RANGE.

Offset and Length Specifications in Unicode Programs

Offset/length specifications are made by appending [+off][(len)] to the name of a data object in operand position, and the specifications are used to access subareas of a data object. This type of programming is no longer completely possible in Unicode systems because, for example when accessing structures with components of different data types, it is not possible to define whether offset and length should be specified in characters or bytes. Furthermore, restrictions have been introduced that forbid access to memory areas outside of flat data objects.

Offset/length specifications for elementary data objects

Offset/length specifications are permitted for character-type and byte-type data objects. The specification of offset and length is interpreted either as a number of characters or as a number of bytes. The rules that determine which data objects in Unicode programs count as character-type or byte-type objects do not allow for offset/length specifications for data objects of numeric data types.

Note

The method of using data objects of type c as containers for storing structures of different types, which are often not known until runtime, in which components are accessed using offset/length access, is no longer possible in Unicode programs. Instead of these containers, the statement CREATE DATA can be used to generate data objects of any structure. To enable access to existing containers, these can be assigned to a field symbol using the CASTING addition of the statement ASSIGN. The COMPONENT addition can then be used to access components.

Offset/length specifications for structures

An offset/length specification for a structure is only permitted in Unicode systems if the structure is either

  • character-type (i.e. it only contains flat character-type components), or it is
  • flat, has a character-type initial fragment according to the Unicode fragment view, and the offset/length specification accesses this initial fragment.

In both cases, the specification of offset and length is interpreted as a number of characters.

Example

The following structure has both character-type and non-character-type components:

BEGIN OF STRUC,
a TYPE c LENGTH 3, "Length 3 characters
b TYPE n LENGTH 4, "Length 4 characters
c TYPE d, "Length 8 characters
d TYPE t, "Length 6 characters
e TYPE decfloat16, "Length 8 bytes
f TYPE c LENGTH 28, "Length28 characters
g TYPE x LENGTH 2, "Length 2 bytes
END OF STRUC.

The Unicode fragment view splits the structure into four areas F1 - F5.

[ aaa | bbbb | cccccccc | ddd | AAA | eeee | fffffffffffff | gg ]
[ F1 | F2 | F3 | F4 | F5 ]

Offset/length access is only possible for the character-type initial fragment F1. Specifications such as struc(21) or struc+7(14) are accepted and are handled as a single field of type c. An access such as struc+57(2), for example, is not permitted in Unicode systems.

Offset/length specifications for actual parameters

For actual parameters specified in PERFORM, in Unicode programs, it is not possible to specify a memory area outside of the actual parameter using offset/length specifications. In particular, it is no longer possible to specify an offset without a length, as this would implicitly set the length of the actual parameter.

Offset/length specification for field symbols

When assigning a memory area to a field symbol using the ASSIGN statement, in Unicode programs it is now only possible to use offset/length specifications to access the memory within the data object. The addition RANGE determines the data object.

Field symbols themselves are also allocated an assignable memory area. This is effective if a field symbol is used as a source in the ASSIGN statement.

In non-Unicode programs, the assignable area is defined by the data area of the current program, which can lead to references being overwritten.

If a data object is entered as a source in ASSIGN, no offset can be specified without a length unless the explicit RANGE addition is specified. Otherwise, this would implicitly set the length of the data object. If the name of a field symbol is specified, its data type in Unicode programs must be flat and elementary if an offset is specified without a length.

Note

Previously, cross-field offset/length accesses could be usefully implemented in the ASSIGN statement for processing repeating groups in structures. In order to enable this in Unicode systems, the ASSIGN statement has been enhanced with the additions RANGE and INCREMENT.

Alignment in Unicode Systems

In Unicode systems, in addition to the alignment requirements for numeric data objects of types i, decfloat16, decfloat34, and f and of deep data objects, all character-type data types are also affected. The alignment is determined by the length requirement of a character in the memory.

As a consequence, in structures with components of different data types, the alignment gaps in Unicode systems may be different to those in non Unicode systems. For enhancements between structures, the Unicode fragment view concept has been introduced, which divides a structure into fragments according to its alignment gaps.

Note

Alignment gaps can also occur at the end of structures, as the overall length of the structure is determined by the component with the largest alignment requirement.

Example

In the following structure, alignment gaps (A) occur in Unicode systems that are not present in non-Unicode systems. The first alignment gap is formed as a result of the alignment of the substructure struc2, the second due to the alignment of the component c of type c>, and the third is due to the component d of type i.

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

Non-Unicode system [ a | b | cccccc | dddd ]
Unicode system [ a | A | b | A | cccccccccccc | AA | dddd ]

Operand Types in Unicode Programs

One of the most important differences between Unicode and non-Unicode programs is the clear distinction between character-type data objects and byte-type data objects, and the restriction of data types whose objects can be viewed as character-type. This has an influence on all statements in which character-type operands are expected, and in particular on character string and byte string processing.

Character-type data objects

In Unicode programs, only the following elementary data objects are now character-type:

Data type Meaning
c Text field
d Date field
n Numerical text
t Time field
string Text string

In addition, structures are character-type if they contain only flat character-type components (only components from the above table with the exception of text strings).

In Unicode programs, a structure can now essentially only be used at an operand position that expects a single field if the structure is character-type. It is then handled in the same way as a data object of type c.

In non-Unicode programs, all flat structures and byte-type data objects are also still handled as character-type data objects (implicit casting).

Note

The incorrect use of structures at operand positions is greatly restricted in Unicode programs. For example, a structure that contains a numeric component can no longer be used at a numeric operand position.

Byte-type data objects

In Unicode programs, elementary data objects of types x and xstringare byte-type. In non-Unicode programs, data objects of this type are generally handled as character-type. Conversely, in non-Unicode programs, at positions in which byte processing takes place (SET BIT, GET BIT and the logical operators O, Z, M), character-type data objects are still expected, while in Unicode programs only byte-type data objects are permitted.

Note

In Unicode programs, the storage of byte strings in character-type containers causes problems, as the byte order of character-type data objects in Unicode systems is platform dependent. In non-Unicode systems, this only applies for data objects of numeric data types. The content of the data objects is interpreted incorrectly if a container of this type is stored persistently and is then imported to an application server with a different byte sequence.

Names in Unicode Programs

Names in Unicode Programs

Only the following characters are allowed in names in Unicode programs:

  1. The letters "A" through "Z"
  2. The digits "0" through "9"
  3. Underscores ("_")

For compatibility reasons, you can also use the characters "%", "$", "?", "-", "#", and "*" but these should be used only in exception cases (for example, for existing program generations) and with good justification. You can also use forward slashes ("/") for namespace prefixes.

Note

Apart from ABAP Objects, non-Unicode programs can also use characters other than the ones listed above. This can cause the following problems in these programs:

  • If characters are used that are not available in all code page supported by SAP, it might not be possible to run certain programs when using a different code page to the one in which they were created.
  • No string templates can be used in a non-Unicode program.

Comments and Literals in Non-Unicode Programs

In non-Unicode systems, no characters should be used in comments unless they are available in all code pages supported by SAP. In the worst case, a program can no longer be executed when a code page other than the one in which it was created is used. We recommend the usage of 7-Bit-ASCII-characters only.

Note

In a Unicode system, all source codes are stored in Unicode and this is why this problem does not occur there. However, even in Unicode programs, do not use characters for comments and literals if they cannot be displayed in non-Unicode programs, so that programs can be transported from a Unicode system to a non-Unicode system without losses during conversion.

Differences between Unicode and Non-Unicode Programs

The ABAP key word documentation describes the ABAP statements for both Unicode and non-Unicode systems. Only Unicode programs can be compiled and executed in Unicode systems. In non-Unicode systems, this is also possible for non-Unicode programs. However, Unicode programs should also be used in non-Unicode systems, for the following reasons:

  • Static type checks are executed in Unicode programs.
  • Byte processing and string processing is separated in Unicode programs.
  • Structures are always handled as structures in Unicode programs.
  • Uncontrolled access to segments of the working memory is not possible in Unicode programs.

This makes Unicode programs easier to understand, more robust, and easier to maintain than non-Unicode programs.

The following section lists the language constructs and statements for which there are differences between Unicode and non-Unicode programs:

  • Comments and Literals in Non-Unicode Programs
  • Names in Unicode Programs
  • Program Structure of Unicode Programs
  • Operand Types in Unicode Programs
  • Alignment in Unicode Systems
  • Offset and Length Specifications in Unicode Programs
  • Access to Memory Sequences in Unicode Programs
  • Conversion of Structures in Unicode Programs
  • Structure Typing in Unicode Programs
  • Structure Enhancements and Unicode Programs
  • String and Byte String Processing in Unicode Programs
  • Function Module Calls in Unicode Programs
  • Open SQL in Unicode Programs
  • File Interface in Unicode Programs
  • Lists in Unicode Systems

Unicode - Overview

Application Server ABAP supports both Unicode and non-Unicode systems. Non-Unicode systems are traditional ABAP systems in which one character is usually represented by one byte. Unicode systems are ABAP systems that are based on Unicode representation and an appropriate operating system and database.

Before Unicode, SAP used various different codes for representing characters in different fonts, such as ASCII, EBCDIC as single-byte code pages, or double-bytecode pages:

  • ASCII (American Standard Code for Information Interchange) encodes every character with one byte. This means that a maximum of 256 characters can be displayed (strictly speaking, standard ASCII only encodes one character using 7 bit and can therefore only represent 128 characters. The extension to 8 bit is introduced with ISO-8859). Examples of common code pages are ISO-8859-1 for Western European, or ISO-8859-5 for Cyrillic fonts.
  • EBCDIC (Extended Binary Coded Decimal Interchange) also encodes each character using one byte, and can therefore also represent 256 characters. For example,EBCDIC 0697/0500 is an IBM format that has been used on the AS/400 (now known as IBM System i)platform for Western European fonts.
  • Double byte code pages require between 1 and 2 bytes per character. This enables the representation of 65,536 characters, of which only 10,000 to 15,000 characters are normally used. For example, the code page SJIS is used for Japanese and BIG5 for traditional Chinese fonts.

Using these character sets, all languages can be handled individually in one AS ABAP. Difficulties arise if texts from different incompatible character sets are mixed in one central system. The exchange of data between systems with incompatible character sets can also lead to problems.

The solution to this problem is the use of a character set that includes all characters at once. This is realized by Unicode (ISO/IEC 10646). A variety of Unicode character representations is possible for the Unicode character set, for example UTF, in which a character can occupy between one and four bytes.

From Release 6.10, the SAP NetWeaver Application Server supports both Unicode and non-Unicode systems. Non-Unicode systems are conventional ABAP systems, in which one character is usually represented by one byte. Unicode systems are ABAP systems that are based on a Unicode character set and which have a corresponding underlying operating system, including a database.

Before Release 6.10, many ABAP programming methods were based on the fact that one character corresponds to one byte. Before a system is converted to Unicode, ABAP programs must therefore be modified at all points where an explicit or implicit assumption is made about the internal length of a character.

ABAP supports this conversion using new syntax rules and new language constructs, whereby emphasis was placed on retaining as much of the existing source code as possible. As a preparation for the conversion to Unicode - but also independently of whether a system will actually be converted to Unicode - the checkbox Unicode checks active can be selected in the program properties. The transaction UCCHECK supports the activation of this check for existing programs. If this property is set, the program is identified as a Unicode program. In a Unicode program, an additional stricter syntax check is performed than in non-Unicode programs. In some cases, statements must also be enhanced by using new additions. A syntactically correct Unicode program will normally run with the same semantics and the same results in Unicode and non-Unicode systems. (Exceptions to this rule are low-level programs that query and evaluate the number of bytes per character). Programs that are required to run in both systems should therefore also be tested on both platforms.

In a Unicode system, only Unicode programs can be executed. Before converting to a Unicode system, the profile parameter abap/unicode_check should be set to "ON" so that only the execution of Unicode programs is permitted. Non-Unicode programs can only be executed in non-Unicode systems. All language constructs that have been introduced for Unicode programs can, however, also be used in non-Unicode programs.

It has been established that existing programs that have been programmed with no errors mostly fulfill the new Unicode rules and therefore require very little modification. Conversely, most programs that require significant changes are due to an error-prone and therefore questionable programming style. Even if you are not planning a conversion to a Unicode system, Unicode programs are preferable because they are more easily maintained and less prone to errors. Just as outdated and dangerous language constructs are declared obsolete and are no longer permitted for use in ABAP objects, the rules for Unicode programs also offer increased security when programming, for example when working with character fields and mixed structures. This applies particularly for the storage of external data (for example using the file interface), which has been completely reviewed for use in Unicode programs. When creating a new program, SAP therefore recommends that you always identify the program as a Unicode program, and older programs can be converted to Unicode in stages.

Statements in Class and Interface Pools

Class and interface pools are the ABAP programs in the Class Library. They are defined using the Class Builder tool in ABAP Workbench and are used as a repository for global classes and interfaces.

  • A program with the program type class pool is launched using the statement CLASS-POOL.
  • A program with the 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 interfaces using the interfaces INTERFACE ... ENDINTERFACE. These interfaces 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 classes 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 methods can provide utility methods, for example, which are invisible 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

An interface pool cannot contain any local declarations or implementations as well as the declaration of the global interface. The 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 alongside 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 Class Builder function allows you to open the associated include programs in ABAP Editor and edit them. Include programs exist for:

  • Each visibility section in the declaration part of the global class
  • Each implementation of a method from the global class
  • Local declarations and implementations in programs
  • Test classes from ABAP Unit

As well as the editing functions for the individual include programs, Class Builder also provides you with a source code-based mode where you can display all the include programs as a single program, and edit them.

Restrictions

Apart from the statements listed above, class pools and interface pools do not require any other statements outside of CLASS - ENDCLASS orINTERFACE - ENDINTERFACE, nor are these statements allowed. The stricter syntax for ABAP Objects applies to all permitted statements.

The following restrictions are particularly important:

  • No processing blocks except methods
Event blocks such as START-OF-SELECTION, AT SELECTION-SCREEN, GET, or AT LINE-SELECTION are not allowed, and neither are dialog modules (defined by MODULE - ENDMODULE). This means that runtime environment events cannot be processed. ABAP Objects has its own event concept. Nor can you define function modules or subroutines 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 shared data areas with other programs
The statements TABLES, 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 mode.
  • No separate screens
Screen processing as implemented in other ABAP programs is not possible. No screens ("dynpros") can be defined in a class pool or interface pool. If you want to use classic dynpros, including selection screens, we recommend that you encapsulate them in function groups. We also recommend that you use alternatives to classic lists, for example classes from SAP List Viewer (ALV) such as CL_SALV_TABLE, for displaying lists in tables.. For simple text output, we recommend browser control wrappers such as dynamic documents or text edit control wrappers.
  • No processing of extracts
In global classes, extract data sets can be edited, since the defining statement FIELD-GROUPS is forbidden in class or interface pools.

Statements for Defining Classes and Interfaces

he following statements define classes and interfaces and their components. You can use them in any ABAP program in which class and interface can be defined.

Statements for Defining Classes

Defining the Declaration Part

CLASS ... DEFINITION ...
...
ENDCLASS ...

Defining the Implementation Part

CLASS ... IMPLEMENTATION ...
...
ENDCLASS ...

Statements for Defining Class Components

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 Interface Components

In interfaces, you can use the same statements to declare interface components as those used in the declaration part of classes.

Note

In the declaration part of a class or in interface, you declare its components, that is, its attributes, methods, and events. You can declare local data types using the TYPES statement. You can also declare alias names for the components of implemented interfaces using the ALIASES statement. In a class, all declarations must belong to one of the four visibility sections introduced by the relevant statement.

The implementation part of a class only contains method implementations in METHOD - ENDMETHOD blocks. In a method, you can only use the statements for method implementations.

No statements other than those listed above are necessary for defining classes or interfaces. Consequently, no other statements are allowed between CLASS and ENDCLASS or INTERFACE - ENDINTERFACE except within methods.

The stricter syntax in ABAP Objects applies to all statements for defining classes and interfaces.

ABAP Objects - Keywords

The following list displays the keywords specially introduced for ABAP objects.

ALIASES Declaration of an alias name
CALL METHOD Call of a method
CLASS ... ENDCLASS Definition of a class
CLASS-DATA Declaration of a static attribute
CLASS-EVENTS Declaration of a static event
CLASS-METHODS Declaration of a static method
CREATE OBJECT Creation of an object
EVENTS Declaration of an instance event
INTERFACE ... ENDINTERFACE Definition of an interface
INTERFACES Including an interface
METHOD ... ENDMETHOD Definition of a method
METHODS Declaration of an Instance method
PRIVATE SECTION Start of private visibility section
PROTECTED SECTION Start of a protected visibility section
PUBLIC SECTION Start of the public visibility section
RAISE EVENT Triggering an event
SET HANDLER Registering an event

Inheritance Events

The example demonstrates the behavior of inheritance events.

Source Text

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.

"Static event

SET HANDLER c4=>cm4.

c1=>cm1( ).
WRITE: / 'c1=>cm1( ):', handle_flag.
c2=>cm1( ).
WRITE: / 'c2=>cm1( ):', handle_flag.
c3=>cm1( ).
WRITE: / 'c3=>cm1( ):', handle_flag.
c2=>cm2( ).
WRITE: / 'c2=>cm2( ):', handle_flag.
c3=>cm2( ).
WRITE: / 'c3=>cm2( ):', handle_flag.
c3=>cm3( ).
WRITE: / 'c3=>cm3( ):', handle_flag.

SKIP.

"Instance event

CREATE OBJECT: oref1, oref2, oref3, oref4.
SET HANDLER oref4->im4 FOR ALL INSTANCES.

oref1->im1( ).
WRITE: / 'oref1->im1( ):', handle_flag.
oref2->im1( ).
WRITE: / 'oref2->im1( ):', handle_flag.
oref3->im1( ).
WRITE: / 'oref3->im1( ):', handle_flag.
oref2->im2( ).
WRITE: / 'oref2->im2( ):', handle_flag.
oref3->im2( ).
WRITE: / 'oref3->im2( ):', handle_flag.
oref3->im3( ).
WRITE: / 'oref3->im3( ):', handle_flag.

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.

  • 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).
  • 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.

Inheritance and Events

After its declaration in a superclass, an event is known in all subclasses of the inheritance tree in which it is visible, and can be triggered 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 which are triggered in classes which more specific or the same as the class for which it is declared. If the event is triggered 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 triggering 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

For event handlers for events declared in interfaces, the above applies correspondingly to the class in which the interface is bound

Inheritance and Instantiation

If you instantiate a subclass, you instantiate all the superclasses at the same time, whereby 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 CREATE PUBLIC|PROTECTED|PRIVATE additions to the CLASS statement control who can create an instance of the class or, in other words, can call its instance constructor.

The effects of this is are:

If you defined a superclass in a path of the inheritance tree using the CREATE PRIVATEaddition, outside users 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 be useful, therefore, also to apply the FINAL addition to a class that was defined using the CREATE PRIVATE addition, in order to prevent a derivation of subclasses. Otherwise subclasses of such superclasses have the implicit CREATE NONE addition.

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, you cannot create objects of subclasses in their superclass, if these are declared using CREATE PROTECTED or CREATE PRIVATE, unless they are friends of its subclasses.

Possible Cases

Superclass with no addition or CREATE PUBLIC

Whether they are friends of the superclass or not, subclasses can have every 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 CREATE PROTECTED addition.

Whether they are friends of the superclass or not, subclasses can have every 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 CREATE PRIVATE addition

Subclass no friend of the superclass

The subclass has the implicit addition CREATE NONE. Since nobody other than the superclass itself can call its instance constructor, the subclass cannot be instantiated. None of the CREATE additions is permitted since this would always lead to the unauthorized publishing of the superclass constructor.

Subclass is 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 superclass' private constructor in any form.

Inheritance and Constructors

Constructors are subject to the following inheritance rules.

Instance Constructors

Each class has an instance constructor called constructor. This name does not comply with the rule of unique component names within a path of an inheritance tree. Consequently, the instance constructors of the individual classes of an inheritance tree are totally independent of each other.

  • Instance constructors of superclasses cannot be redefined in subclasses.
  • They cannot be called explicitly using [CALL METHOD] constructor.

This avoids namespace conflicts.

The instance constructor of a class is called when you create an object using the CREATE OBJECT statement. Since a subclass inherits all attributes from its superclasses that are visible to it, and since the content of these attributes can be set by instance constructors of its classes, the instance constructor of a subclass is responsible for ensuring that the instance constructors of all superclasses are called as well. This requires that the instance constructor of each subclass contains a [CALL METHOD] super->constructor call of the instance constructor of the direct superclass even if it is not explicitly declared. Exceptions to this rule are the direct subclasses of the root node object.

In superclasses that do not have an explicitly defined instance constructor, the implicit instance constructor is called. This constructor automatically ensures that the instance constructor of the next higher superclass is called.

When instance constructors are called, all non-optional input parameters of these constructors must be populated, as follows:

  • Parameter population at CREATE OBJECT

    Starting from the class of the created objects, the first explicitly defined instance constructor in the corresponding path of the inheritance tree is taken into account. This is the instance constructor of the class itself or the first explicitly defined instance constructor of a superclass.
  • Population at [CALL METHOD] super->constructor

    Starting from the direct superclass, the first explicitly defined instance constructor in the corresponding path of the inheritance tree is taken into account.

The interface of the first explicitly defined instance constructor is populated as is the case with a normal method - that is,

  • If no input parameters exist, no parameters are passed.
  • Optional input parameters can be populated using EXPORTING.
  • Non-optional input parameters must be populated 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.

Both at CREATE OBJECT and at [CALL METHOD] super->constructor, the next possible explicit instance constructor must be taken into account. If one exists, its interface must be populated. The same applies to exception handling in instance constructors. Using inheritance requires in-depth knowledge of the entire inheritance tree since when an object of a class is created that resides on a deep level of the tree, parameters may have to be passed to the constructor of a class that resides closer to the root node.

The instance constructor of a subclass is split into two parts by the [CALL METHOD] super->constructor call, which is required from a syntactical point of view. In the statements before the call, the constructor behaves like a static method. This means it cannot access the instance attributes of its class. It is only after the call that instance attributes can be addressed. The statements before the call are used to determine actual parameters for the interface of the instance constructor of a superclass. Only static attributes or local data can be used for this.

When a subclass is instantiated, the system makes a nested call of the instance constructors from the subclass to the superclasses where the instance attributes can only be addressed at the deepest nesting level, that is, in the highest superclass. When the system returns to the constructors of the underlying subclasses, their instance attributes can then also be successively addressed.

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 it is implemented in the class of the instance constructor and not as the possibly redefined method of the subclass to be instantiated. This is an exception to the rule that when instance methods are called the implementation is always called in the class to whose instance the reference currently points.

Static Constructors

Each class has a static constructor called class_constructor. As far as the namespace in an inheritance tree is concerned, the static constructor is subject to the same rules as the instance constructor.

The static constructor is called when a subclass is first addressed within a program. However, all preceding static constructors of the entire inheritance tree must have been executed before. Otherwise, a static constructor can only be called once at the runtime of the program. This is why when a subclass is addressed for the first time the system searches the next higher superclass whose static constructor has not yet been called. This static constructor is executed first. Afterwards the constructors of all subsequent subclasses are called successively down to the subclass addressed.

Inheritance and Static Components

Static components, like all components, exist only once in each inheritance tree, and can be used as 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 addressed, whether the static component is used internally or externally. This is important for:

  • Calling the static constructors.

    Static constructors are called the first time you address a class. If you address a static component 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 assigned to a single class; instead they are assigned 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.
  • The registration 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 triggered by a method of the subclass or one of its subclasses. If the event is triggered 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.

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 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'.

Example

For an example of static events, see Inheritance Events.

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 lie within a single namespace and must have unique names. Private components, in contrast, must only be named uniquely within a class.

When methods are redefined, the newly implemented method hides 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 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. If the OPEN FOR PACKAGE addition is not specified, the protected area is only visible in the class itself and in all its subclasses. If the addition is specified, the protected area is also visible in the current package. If the OPEN FOR PACKAGEaddition is not specified protected seems the same as private from outside. If the addition is specified, within the current package protected has the effect of public and from outside it seems like 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 affected - 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 Interfaces

Interfaces are independent constructs in ABAP Objects that support polymorphism of classses. 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. Having been implemented, interface methods are fully functioning components of a class and can be redefined in subclasses.

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.

Abstract and Final Methods and Classes

Using the ABSTRACT and FINAL additions of the METHODS and CLASS statements, you can define abstract and final methods or classes.

Abstract methods are declared in abstract classes and cannot be implemented in the same class but only in a subclass of the inheritance tree. Abstract classes can consequently not be instantiated. A non-abstract method is a concrete method. Except for the instance constructor, the concrete instance methods of a class can also call its abstract methods.

Final methods cannot be redefined in subclasses. Final classes cannot have any more subclasses and constitute the final node of an inheritance tree.

Note

In classes that are abstract and final at the same time, only the static components can be used. Instance components can be declared, but these cannot be used. For this reason, it is recommended that you specify both ABSTRACT and FINAL only for static classes.

Redefining Methods

Each subclass contains the components of all classes that lie 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 REDEFINITION addition of the METHODS statement in order to adjust them to the requested specialization. The interface of a redefined method cannot be changed. The method is merely re-implemented 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 retained there. The implementation of the redefinition is generated additionally with 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 CALL METHOD [me->]m2 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 the pseudo reference super-> can be used to access the obscured method, for example, to adopt and supplement its functions.

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 statement. 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 sectionof 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.

Definition of Classes and Interfaces

In ABAP Objects, you can define classes and interfaces either globally or locally. You define global classes and interfaces with the Class Builder tool in the ABAP Workbench; they are then stored centrally in the class library in the repository. All ABAP programs in an AS ABAP can access these global classes and interfaces. Conversely, you can only use local classes and interfaces in the program that defines them. When an ABAP program uses a class, the system searches first for a local class, then for a global class of the same name. Otherwise, there is no difference in the use of local and global classes or interfaces.

Since local classes are only used by one program, it is generally sufficient to define the public interface - that is, the outwardly visible components appropriate for this program. Conversely, each global class is available throughout the system, which means that its public interface can only be typed with reference to data types that are themselves visible throughout the system.

The following sections describe classes and interfaces using the syntax for the definition of local classes and interfaces in an ABAP program. For the definition of global classes and interfaces, all language elements have a counterpart in the operating elements of the Class Builder. For more information, see the documentation for the Class Builder.

Defining Local Classes

Local classes consist of ABAP source code enclosed between the CLASS - ENDCLASS statements. A complete class definition consists of a declaration part and, if necessary, an implementation part.

The declaration part of a class class consists of one statement block:

CLASS class DEFINITION.
...
ENDCLASS.

This declaration part contains the declaration of the components (attributes, methods, events) of a 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. In global classes, the declaration part belongs to the global data declarations and should be at the start of the program.

If methods are declared in the declaration part of a class, the class needs an implementation part, which consists of one statement block:

CLASS class IMPLEMENTATION.
...
ENDCLASS.

The implementation part of a class contains the implementation of all the methods of this 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 (as in subroutines), 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 Local Interfaces

You define the local interface intf using the

INTERFACE intf. and
...
ENDINTERFACE. statements.

The definition contains all the components (attributes, methods, events) of the interface. In interfaces, you can define the same components as in classes. You cannot assign the components of a interface explicitly to a visibility section, because interface components always extend the public area of the class. There is no implementation part for interfaces, since the methods of an interface must be implemented in the same class that implements the interface.

Blog Archive