| Local classes |
|
| Global classes |
|
| Addition | Notes |
| `PUBLIC` | Creates a global class |
| `FINAL` | The class does not allow inheritance. |
| `CREATE PUBLIC` | The class is instantiable anywhere. |
| `CREATE PROTECTED` | The class can only be instantiated in methods of its [subclasses](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abensubclass_glosry.htm "Glossary Entry"), of the class itself, and of its [friends](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenfriend_glosry.htm "Glossary Entry"). |
| `CREATE PRIVATE` | The class can only be instantiated in methods of the class itself or of its friends. Hence, it cannot be instantiated as an inherited component of subclasses. |
| `INHERITING FROM superclass` | As the name implies, it is used to inherit from a visible [superclass](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abensuperclass_glosry.htm). If the addition is not specified, the created class implicitly inherits from the predefined empty, abstract class `object` (the root object). |
| `ABSTRACT` | To define [abstract](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenabstract_glosry.htm) classes. These classes cannot be instantiated. These classes can contain both abstract methods and non-abstract methods. Abstract methods can only be implemented in [subclasses](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abensubclass_glosry.htm) by redefinition. See a simple implementation example [here](#excursion-example-interface). |
| `[GLOBAL|LOCAL] FRIENDS class` | - Used to define [friendships](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenfriend_glosry.htm) (also possible for interfaces). Friends of a class have unrestricted access to all components of that class. - `GLOBAL FRIENDS`: Used in global classes (together with the `PUBLIC` addition) to grant friendship to other global classes and interfaces - `FRIENDS`: For local classes, e.g. local classes granting friendship to other local classes or the global class of the class pool - `LOCAL FRIENDS`: Used for global classes to grant friendship to local classes and interfaces in its own class pool. However, it is a dedicated statement, as shown in the [Friendship](#friendship) section. |
| `FOR TESTING` | For [ABAP Unit](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenabap_unit_glosry.htm) tests. Find more information in the [ABAP Unit Tests](14_ABAP_Unit_Tests.md) cheat sheet. |
| `FOR BEHAVIOR OF` | To define [ABAP behavior pools](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenbehavior_pool_glosry.htm). Find more information in the [ABAP for RAP: Entity Manipulation Language (ABAP EML)](08_EML_ABAP_for_RAP.md) cheat sheet. |
| `DEFINITION DEFERRED` | Makes a local class known in a program before the actual class definition. It is typically used in test classes of ABAP Unit. Find more information [here](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapclass_deferred.htm). |
PUBLIC SECTION. |
Components declared in this section can be accessed from within the class and from all users of the class. |
PROTECTED SECTION. |
Components declared in this section can be accessed from within the class and subclasses as well as friends - concepts related to inheritance. |
PRIVATE SECTION. |
Components declared in this section can only be accessed from within the class in which they are declared and its friends. |
oref->some_static_method( ).| Syntax Example | Details |
| ``` abap CLASS zcl_demo DEFINITION PUBLIC FINAL CREATE PUBLIC . ``` |
- `... PUBLIC ...`: Specifies that the class is a global class, available globally within the class library. Most of the subsequent snippets use the `PUBLIC` addition as the focus is on global classes. - `... FINAL ...`: Specifies that the class cannot have any subclasses, effectively prohibiting inheritance. This addition seals off a branch of the inheritance tree. In final classes, all methods are automatically final. - `... CREATE PUBLIC ...`: Specifies that the class can be instantiated wherever it is visible. |
| ``` abap CLASS zcl_demo DEFINITION PUBLIC CREATE PUBLIC . ``` |
This class permits inheritance because it does not include the `FINAL` addition. Subclasses can be derived from this superclass. |
| ``` abap CLASS zcl_demo DEFINITION PUBLIC CREATE PROTECTED . ``` |
- This class permits inheritance because it does not include the `FINAL` addition. - `... CREATE PROTECTED ...`: Specifies that the class can only be instantiated within its own methods, its subclasses' methods, or those of its friends. |
| ``` abap CLASS zcl_demo DEFINITION FINAL CREATE PRIVATE . ``` |
- This class does not permit inheritance because it includes the `FINAL` addition. - `... CREATE PRIVATE ...`: Specifies that the class can only be instantiated within its own methods or those of its friends. It cannot be instantiated as a component of (not befriended) subclasses. - Consider the implications of defining a superclass in this manner: - External users cannot instantiate a subclass. - If inheritance is allowed, subclasses cannot instantiate themselves though. This is because they cannot access the superclass's instance constructor, preventing the creation of subclass instances. However, this can be altered if the subclass is a friend of the superclass. - Similarly, subclass objects cannot be created within their superclass if declared using `CREATE PROTECTED` or `CREATE PRIVATE`. This is only possible if the superclasses are friends with their subclasses. - The `FINAL` addition can be beneficial with `CREATE PRIVATE` to prevent the derivation of subclasses. - Note: In each class, the `CREATE PUBLIC`, `CREATE PROTECTED`, and `CREATE PRIVATE` additions of the `CLASS` statement control who can create an instance of the class and who can call its instance constructor. |
| ``` abap CLASS zcl_demo DEFINITION PUBLIC ABSTRACT CREATE ... ``` |
- `... ABSTRACT ...`: - Defines abstract classes - Abstract classes cannot be instantiated. - To use the instance components of an abstract class, you can instantiate a subclass of that class. - Abstract classes may contain both abstract and concrete instance methods. However, abstract methods are not implemented within abstract classes. - By adding the `FINAL` addition, abstract classes can be made final. In these cases, only static components are usable. While instance components may be declared, they are not usable. |
| ``` abap CLASS zcl_sub DEFINITION INHERITING FROM zcl_demo ... ``` |
- `... INHERITING FROM ...`: - Can be specified in subclasses inheriting from visible superclasses - If not specified, the class implicitly inherits from the predefined, empty, abstract class `OBJECT` (the root object). - A subclass inherits all components of the superclasses. - For example, if an internal table `itab` is declared as a static component in superclass `zcl_super`, subclasses can refer to `itab` directly, not necessarily by specifying the class name as with `zcl_super=>itab` (which is also possible). - If the superclass defines a type, subclasses cannot define a type with the same name. - The visibility of the components remains unchanged. - Only the public and protected components of the superclass are visible in the subclass. - Private components of superclasses are inaccessible in subclasses. - The properties of inherited components are immutable. However, subclasses can declare additional components (with unique names) and redefine inherited methods without altering the interface. - Upon instantiation of a subclass, all superclasses are also instantiated, ensuring the initialization of superclass attributes through calling superclass constructors. |
| Syntax Example | Details |
| ``` abap METHODS some_meth FINAL ... ``` |
- Declares final methods - These methods cannot be overridden in subclasses. - Note: In final classes, all methods are inherently final. Therefore, the `FINAL` addition cannot be specified. Instance constructors are always final, but the use of the `FINAL` addition is optional. |
| ``` abap METHODS some_meth ABSTRACT ... ``` |
- Declares abstract methods - Can only be used in abstract classes - You can implement these methods in a subclass (by redefining using the `REDEFINITION`addition), not in the abstract class itself. When declared, there is no implementation part in the abstract class. - All instance methods can be declared as abstract, except for instance constructors. - Private methods cannot be redefined and can therefore not be declared as abstract. - If abstract methods are declared in classes that are both abstract and final, they cannot be implemented. Therefore, the methods are not usable. - In interfaces, methods are implicitly abstract as interfaces do not contain method implementations. |
| ``` abap "Instance constructor METHODS constructor. "Static constructor CLASS-METHODS class_constructor. ``` |
- Instance constructors (`constructor`): - Subclasses cannot redefine the instance constructors of superclasses. - These constructors are automatically invoked when creating an object, not explicitly called. - In inheritance, a subclass's instance constructor must call the instance constructors of all its superclasses. This requires calling `super->constructor( ).` to call the instance constructor of the direct superclass, even if the superclass does not explicitly declare the instance constructor. Note that any non-optional importing parameters must be filled. - Static constructors (`class_constructor`): - These constructors are implicitly available in all classes, whether declared or not. - They are called when creating a class instance for the first time in an ABAP program or when addressing a static component, excluding types and constants. - In inheritance, the static constructors of all classes up the inheritance tree are called first. - A static constructor can only be called once during program runtime. |
| ``` abap METHODS some_meth REDEFINITION. METHODS another_meth FINAL REDEFINITION. ``` |
- Specified in subclasses to redefine inherited methods from superclasses. - The method's implementation is expected to reimplement the inherited method. However, the subclass's new implementation conceals the superclass's implementation. - The redefined method accesses the private components of its class, not any similarly named private components in the superclass. - The superclass's implementation can be called in the redefined method using the [pseudo reference](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenpseudo_reference_glosry.htm "Glossary Entry") `super->meth( ).`. Note that non-optional importing parameters must be filled. - The redefinition is valid for subclasses until the method is redefined again. - The `FINAL` addition can be specified, preventing further redefinition of the method in other subclasses. |
| Addition | Notes |
| [`ALIASES ... FOR ...`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapaliases.htm) |
Specifies alias names for the interface components. The components can then be addressed using the alias name.
```abap "Local interface in a CCIMP include INTERFACE lif. METHODS some_method. DATA some_string type string. ENDINTERFACE. "Local class in a CCIMP include implementing the interface CLASS lcl DEFINITION. PUBLIC SECTION. INTERFACES lif. ALIASES meth FOR lif~some_method. ALIASES str FOR lif~some_string. ENDCLASS. CLASS lcl IMPLEMENTATION. METHOD meth. "This syntax is also possible: METHOD lif~some_method. ... DATA(string1) = str. "This sytanx is also possible. However, when you have already addressed the component "with the alias as in the assignment above, the following statement shows a syntax warning. "DATA(string2) = lif~some_string. ENDMETHOD. ENDCLASS. ``` |
| [`ABSTRACT METHODS`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapinterfaces_class.htm) |
- Specifies instance methods as abstract.
- Multiple methods can be specified.
- The addition can only be used when the whole class is defined as abstract.
``` abap INTERFACE lif3. METHODS meth1. METHODS meth2. ENDINTERFACE. "Local abstract class "meth1 is specified as abstract method, meth2 is not. "Therefore, only meth2 must be implemented. meth1 must "be implemented by the subclasses. CLASS lcl3 DEFINITION ABSTRACT. PUBLIC SECTION. INTERFACES lif3 ABSTRACT METHODS meth1. ENDCLASS. CLASS lcl3 IMPLEMENTATION. METHOD lif3~meth2. ... ENDMETHOD. ENDCLASS. CLASS lcl4 DEFINITION INHERITING FROM lcl3. PUBLIC SECTION. METHODS lif3~meth1 REDEFINITION. ENDCLASS. CLASS lcl4 IMPLEMENTATION. METHOD lif3~meth1. ... ENDMETHOD. ENDCLASS. ``` |
| [`ALL METHODS ABSTRACT`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapinterfaces_class.htm) |
See above. With this addition, all methods are specified as abstract.
``` abap INTERFACE lif. METHODS meth1. METHODS meth2. ENDINTERFACE. "Local abstract class "All methods are specified as abstract methods. "Therefore, all methods of the interface must be implemented "by the subclasses. CLASS lcl1 DEFINITION ABSTRACT. PUBLIC SECTION. INTERFACES lif ALL METHODS ABSTRACT. ENDCLASS. CLASS lcl1 IMPLEMENTATION. ENDCLASS. CLASS lcl2 DEFINITION INHERITING FROM lcl1. PUBLIC SECTION. METHODS lif~meth1 REDEFINITION. METHODS lif~meth2 REDEFINITION. ENDCLASS. CLASS lcl2 IMPLEMENTATION. METHOD lif~meth1. ... ENDMETHOD. METHOD lif~meth2. ... ENDMETHOD. ENDCLASS. ``` |
| [`FINAL METHODS`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapinterfaces_class.htm) |
Specifies methods as final so they cannot be further redefined. Multiple methods can be specified.
```abap INTERFACE lif. METHODS meth1. METHODS meth2. ENDINTERFACE. "meth1 is specified as final method, meth2 is not. "Therefore, only meth2 can be further redefined in subclasses. CLASS lcl1 DEFINITION. PUBLIC SECTION. INTERFACES lif FINAL METHODS meth1. ENDCLASS. CLASS lcl1 IMPLEMENTATION. METHOD lif~meth1. ... ENDMETHOD. METHOD lif~meth2. ... ENDMETHOD. ENDCLASS. CLASS lcl2 DEFINITION INHERITING FROM lcl1. PUBLIC SECTION. "meth1 cannot be redefined as it is declared as final in the superclass. "METHODS lif~meth1 REDEFINITION. METHODS lif~meth2 REDEFINITION. ENDCLASS. CLASS lcl2 IMPLEMENTATION. METHOD lif~meth2. ... ENDMETHOD. ENDCLASS. ``` |
| [`ALL METHODS FINAL`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapinterfaces_class.htm) |
See above. With this addition, all methods are specified as final.
``` abap INTERFACE lif. METHODS meth1. METHODS meth2. ENDINTERFACE. "All methods are specified as final. Therefore, they "cannot be further redefined in subclasses. CLASS lcl1 DEFINITION. PUBLIC SECTION. INTERFACES lif ALL METHODS FINAL. METHODS meth3. ENDCLASS. CLASS lcl1 IMPLEMENTATION. METHOD lif~meth1. ... ENDMETHOD. METHOD lif~meth2. ... ENDMETHOD. METHOD meth3. ... ENDMETHOD. ENDCLASS. CLASS lcl2 DEFINITION INHERITING FROM lcl1. PUBLIC SECTION. "meth1 and meth2 cannot be redefined. "METHODS lif~meth1 REDEFINITION. "METHODS lif~meth2 REDEFINITION. METHODS meth3 REDEFINITION. ENDCLASS. CLASS lcl2 IMPLEMENTATION. METHOD meth3. ... ENDMETHOD. ENDCLASS. ``` |
| [`DATA VALUES`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/ABAPINTERFACES_CLASS.html) |
- Used to assign start values for attributes
- Works in the style of `DATA ... VALUE ...` statements, e.g. `DATA number TYPE i VALUE 123`.
``` abap INTERFACE lif. METHODS meth1 RETURNING VALUE(result) TYPE i. DATA num1 TYPE i. DATA num2 TYPE i. CLASS-DATA num3 TYPE i. ENDINTERFACE. CLASS lcl1 DEFINITION. PUBLIC SECTION. INTERFACES lif DATA VALUES num1 = 1 num2 = 3 num3 = 6. ENDCLASS. CLASS lcl1 IMPLEMENTATION. METHOD lif~meth1. result = lif~num1 + lif~num2 + lif~num3. ENDMETHOD. ENDCLASS. CLASS lcl3 DEFINITION. PUBLIC SECTION. CLASS-METHODS meth. ENDCLASS. CLASS lcl3 IMPLEMENTATION. METHOD meth. "result: 10 DATA(result) = NEW lcl1( )->lif~meth1( ). ENDMETHOD. ENDCLASS. ``` |
| [`PARTIALLY IMPLEMENTED`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/ABAPINTERFACES_PARTIALLY.html) |
- Relevant only for test classes.
- When you use the `PARTIALLY IMPLEMENTED` addition in test classes, you are not forced to implement all of the concrete non-optional methods.
- It is particularly useful for interfaces to implement test doubles, and not all methods are necessary.
- See the [ABAP Unit Tests](14_ABAP_Unit_Tests.md) cheat sheet.
``` abap "Test double class in a test include CLASS ltd_test_double DEFINITION FOR TESTING. PUBLIC SECTION. INTERFACES some_intf PARTIALLY IMPLEMENTED. ENDCLASS. CLASS ltd_test_double IMPLEMENTATION. METHOD some_intf~some_meth. ... ENDMETHOD. ENDCLASS. ``` |
|
[`DEFAULT IGNORE`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapmethods_default.htm)
(addition used in the interface definition) |
- Marks the implementation of methods as optional
- Defines a default behavior when non-implemented methods are called. When a method with such a declaration is called without an implementation, it behaves as though no implementation exists.
- Can only be used in interfaces for instance and static methods (except constructors and test methods)
``` abap INTERFACE lif. METHODS meth1 DEFAULT IGNORE. METHODS meth2. ENDINTERFACE. CLASS lcl1 DEFINITION. PUBLIC SECTION. INTERFACES lif. ENDCLASS. "The class implementation does not include the optional "implementation of lif~meth1. CLASS lcl1 IMPLEMENTATION. METHOD lif~meth2. ... ENDMETHOD. ENDCLASS. CLASS lcl2 DEFINITION. PUBLIC SECTION. INTERFACES lif. ENDCLASS. "The class implementation includes the optional "implementation of lif~meth1. CLASS lcl2 IMPLEMENTATION. METHOD lif~meth1. ... ENDMETHOD. METHOD lif~meth2. ... ENDMETHOD. ENDCLASS. CLASS lcl3 DEFINITION. PUBLIC SECTION. class-methods meth3. ENDCLASS. "The class implementation includes the optional "implementation of lif~meth1. CLASS lcl3 IMPLEMENTATION. METHOD meth3. DATA(oref1) = NEW lcl1( ). DATA(oref2) = NEW lcl2( ). "Although not implemented, meth1 can be 'called' (i.e. "it can be specified to be called). In this case, it is "just like calling a method with empty implementation. oref1->lif~meth1( ). oref1->lif~meth2( ). "In this class, both methods are implemented. oref2->lif~meth1( ). oref2->lif~meth2( ). ENDMETHOD. ENDCLASS. ``` |
|
[`DEFAULT FAIL`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapmethods_default.htm)
(addition used in the interface definition) |
See above. The behavior with this addition is that when an unimplemented method is called, the `CX_SY_DYN_CALL_ILLEGAL_METHOD` exception is raised.
``` abap INTERFACE lif. METHODS meth1 DEFAULT FAIL. METHODS meth2. ENDINTERFACE. CLASS lcl1 DEFINITION. PUBLIC SECTION. INTERFACES lif. ENDCLASS. "The class implementation does not include the optional "implementation of lif~meth1. CLASS lcl1 IMPLEMENTATION. METHOD lif~meth2. ... ENDMETHOD. ENDCLASS. CLASS lcl2 DEFINITION. PUBLIC SECTION. INTERFACES lif. ENDCLASS. "The class implementation includes the optional "implementation of lif~meth1. CLASS lcl2 IMPLEMENTATION. METHOD lif~meth1. ... ENDMETHOD. METHOD lif~meth2. ... ENDMETHOD. ENDCLASS. CLASS lcl3 DEFINITION. PUBLIC SECTION. CLASS-METHODS meth3. ENDCLASS. "The class implementation includes the optional "implementation of lif~meth1. CLASS lcl3 IMPLEMENTATION. METHOD meth3. DATA(oref1) = NEW lcl1( ). DATA(oref2) = NEW lcl2( ). "Although not implemented, meth1 can be 'called' (i.e. "it can be specified to be called). "However, with the DEFAULT FAIL addition, an exception is "raised. TRY. oref1->lif~meth1( ). CATCH cx_sy_dyn_call_illegal_method INTO DATA(error). DATA(error_text) = error->get_text( ). ENDTRY. oref1->lif~meth2( ). "In this class, both methods are implemented. oref2->lif~meth1( ). oref2->lif~meth2( ). ENDMETHOD. ENDCLASS. ``` |
| Class include | Code |
| Global class |
- Create a new global class (the example uses the name `zcl_demo_abap`) and copy and paste the following code in the *Global Class* tab in ADT.
- The class has a type and method declaration in the private section. They are used in the local class.
- Once activated (and the code of the other includes has been inserted), you can choose *F9* in ADT to run the class.
- When running the class, a method of the local class that is declared in the private section there is called. As a result of this method call, a string is assigned to an attribute that is also declared in the private section of the local class. This attribute is accessed by the global class, and finally displayed in the ADT console.
```abap CLASS zcl_demo_abap DEFINITION PUBLIC FINAL CREATE PUBLIC . PUBLIC SECTION. INTERFACES if_oo_adt_classrun. PROTECTED SECTION. PRIVATE SECTION. TYPES str TYPE string. CLASS-METHODS get_hello RETURNING VALUE(hello) TYPE str. ENDCLASS. CLASS zcl_demo_abap IMPLEMENTATION. METHOD if_oo_adt_classrun~main. local_class=>say_hello( ). DATA(hello) = local_class=>hello. out->write( hello ). ENDMETHOD. METHOD get_hello. hello = `Hello`. ENDMETHOD. ENDCLASS. ``` |
| CCDEF include (Class-relevant Local Types tab in ADT) |
- Regarding the includes, see the information in section [Excursion: Class Pool and Include Programs](#excursion-class-pool-and-include-programs)
- The `LOCAL FRIENDS` addition makes the local class a friend of the global class. The private components of the global class can then be accessed by the local class.
```abap CLASS local_class DEFINITION DEFERRED. CLASS zcl_demo_abap DEFINITION LOCAL FRIENDS local_class. ``` |
| CCIMP include (Local Types tab in ADT) |
- The `FRIENDS` addition makes the global class a friend of the local class. The private components of the local class can then be accessed by the global class.
- A type declared in the private section of the global class is used to type an attribute.
- The method, which is also declared in the private section, includes a method call in the implementation. It is a method declared in the private section of the global class.
```abap CLASS local_class DEFINITION FRIENDS zcl_demo_abap. PUBLIC SECTION. PROTECTED SECTION. PRIVATE SECTION. CLASS-DATA hello TYPE zcl_demo_abap=>str. CLASS-METHODS say_hello. ENDCLASS. CLASS local_class IMPLEMENTATION. METHOD say_hello. hello = |{ zcl_demo_abap=>get_hello( ) } { sy-uname }.|. ENDMETHOD. ENDCLASS. ``` |
| Class include | Code |
| Global class | ``` abap CLASS zcl_demo_abap DEFINITION PUBLIC FINAL CREATE PUBLIC . PUBLIC SECTION. INTERFACES if_oo_adt_classrun. PROTECTED SECTION. PRIVATE SECTION. ENDCLASS. CLASS zcl_demo_abap IMPLEMENTATION. METHOD if_oo_adt_classrun~main. "Saying hello in English DATA(oref_en) = lcl_factory_cl=>create_hello( lif_factory=>en ). DATA(hello_en) = oref_en->say_hello( ). out->write( hello_en ). "Saying hello in French DATA(oref_fr) = lcl_factory_cl=>create_hello( lif_factory=>fr ). DATA(hello_fr) = oref_fr->say_hello( ). out->write( hello_fr ). "Saying hello in Italian DATA(oref_it) = lcl_factory_cl=>create_hello( lif_factory=>it ). DATA(hello_it) = oref_it->say_hello( ). out->write( hello_it ). "Saying hello in Spanish DATA(oref_es) = lcl_factory_cl=>create_hello( lif_factory=>es ). DATA(hello_es) = oref_es->say_hello( ). out->write( hello_es ). "Saying hello in German DATA(oref_de) = lcl_factory_cl=>create_hello( lif_factory=>de ). DATA(hello_de) = oref_de->say_hello( ). out->write( hello_de ). "Default hello DATA(oref_default) = lcl_factory_cl=>create_hello( lif_factory=>init ). DATA(hello_default) = oref_default->say_hello( ). out->write( hello_default ). ENDMETHOD. ENDCLASS. ``` |
| CCIMP include (Local Types tab in ADT) | ``` abap INTERFACE lif_factory. TYPES: basetype TYPE i, BEGIN OF ENUM enum_langu BASE TYPE basetype, init VALUE IS INITIAL, en VALUE 1, fr VALUE 2, it VALUE 3, es VALUE 4, de VALUE 5, END OF ENUM enum_langu. METHODS say_hello RETURNING VALUE(hi) TYPE string. ENDINTERFACE. CLASS lcl_en DEFINITION FINAL CREATE PUBLIC. PUBLIC SECTION. INTERFACES lif_factory. PROTECTED SECTION. PRIVATE SECTION. ENDCLASS. CLASS lcl_en IMPLEMENTATION. METHOD lif_factory~say_hello. hi = `Hi`. ENDMETHOD. ENDCLASS. CLASS lcl_fr DEFINITION FINAL CREATE PUBLIC. PUBLIC SECTION. INTERFACES lif_factory. PROTECTED SECTION. PRIVATE SECTION. ENDCLASS. CLASS lcl_fr IMPLEMENTATION. METHOD lif_factory~say_hello. hi = `Salut`. ENDMETHOD. ENDCLASS. CLASS lcl_it DEFINITION FINAL CREATE PUBLIC. PUBLIC SECTION. INTERFACES lif_factory. PROTECTED SECTION. PRIVATE SECTION. ENDCLASS. CLASS lcl_it IMPLEMENTATION. METHOD lif_factory~say_hello. hi = `Ciao`. ENDMETHOD. ENDCLASS. CLASS lcl_es DEFINITION FINAL CREATE PUBLIC. PUBLIC SECTION. INTERFACES lif_factory. PROTECTED SECTION. PRIVATE SECTION. ENDCLASS. CLASS lcl_es IMPLEMENTATION. METHOD lif_factory~say_hello. hi = `Hola`. ENDMETHOD. ENDCLASS. CLASS lcl_de DEFINITION FINAL CREATE PUBLIC. PUBLIC SECTION. INTERFACES lif_factory. PROTECTED SECTION. PRIVATE SECTION. ENDCLASS. CLASS lcl_de IMPLEMENTATION. METHOD lif_factory~say_hello. hi = `Hallo`. ENDMETHOD. ENDCLASS. ********************************************************************** CLASS lcl_factory_cl DEFINITION FINAL CREATE PRIVATE. PUBLIC SECTION. CLASS-METHODS create_hello IMPORTING language TYPE lif_factory=>enum_langu RETURNING VALUE(hello) TYPE REF TO lif_factory. PROTECTED SECTION. PRIVATE SECTION. ENDCLASS. CLASS lcl_factory_cl IMPLEMENTATION. METHOD create_hello. hello = SWITCH #( language WHEN lif_factory=>en THEN NEW lcl_en( ) WHEN lif_factory=>fr THEN NEW lcl_fr( ) WHEN lif_factory=>it THEN NEW lcl_it( ) WHEN lif_factory=>es THEN NEW lcl_es( ) WHEN lif_factory=>de THEN NEW lcl_de( ) "E.g. raising an exception or returning a default object ELSE NEW lcl_en( ) ). ENDMETHOD. ENDCLASS. ``` |
| Class include | Code |
| Global class | ``` abap CLASS zcl_demo_abap DEFINITION PUBLIC FINAL CREATE PUBLIC . PUBLIC SECTION. INTERFACES if_oo_adt_classrun. PROTECTED SECTION. PRIVATE SECTION. ENDCLASS. CLASS zcl_demo_abap IMPLEMENTATION. METHOD if_oo_adt_classrun~main. "Internal table to store and display object reference variable names and "time stamp values TYPES: BEGIN OF s_ts, name TYPE string, timestamp_static TYPE utclong, timestamp_instance TYPE utclong, END OF s_ts. DATA ts_tab TYPE TABLE OF s_ts WITH EMPTY KEY. "Object creation as follows is not possible "DATA(oref) = NEW lcl_singleton( ). "Creating object DATA(oref1) = lcl_singleton=>get_obj( ). "Retrieving time stamps, and adding the values to the internal table created above "for display purposes oref1->get_timestamps( IMPORTING ts_static = DATA(ts_static) ts_instance = DATA(ts_instance) ). APPEND VALUE #( name = `oref1` timestamp_static = ts_static timestamp_instance = ts_instance ) TO ts_tab. "Adding entries to a log table (represented by a private static attribute in the local class) oref1->add_log( |Text 1 added at { utclong_current( ) } (using oref1)| ). oref1->add_log( |Text 2 added at { utclong_current( ) } (using oref1)| ). "Creating more objects (however, the one created previously is returned) and adding entries "to the log table "Time stamp values are also added the to the internal table for display purposes DATA(oref2) = lcl_singleton=>get_obj( ). oref2->get_timestamps( IMPORTING ts_static = ts_static ts_instance = ts_instance ). APPEND VALUE #( name = `oref2` timestamp_static = ts_static timestamp_instance = ts_instance ) TO ts_tab. oref2->add_log( |Text 3 added at { utclong_current( ) } (using oref2)| ). oref2->add_log( |Text 4 added at { utclong_current( ) } (using oref2)| ). oref1->add_log( |Text 5 added at { utclong_current( ) } (using oref1)| ). DATA(oref3) = lcl_singleton=>get_obj( ). oref3->get_timestamps( IMPORTING ts_static = ts_static ts_instance = ts_instance ). APPEND VALUE #( name = `oref3` timestamp_static = ts_static timestamp_instance = ts_instance ) TO ts_tab. oref3->add_log( |Text 6 added at { utclong_current( ) } (using oref3)| ). oref3->add_log( |Text 7 added at { utclong_current( ) } (using oref3)| ). oref1->add_log( |Text 8 added at { utclong_current( ) } (using oref1)| ). oref2->add_log( |Text 9 added at { utclong_current( ) } (using oref2)| ). oref3->add_log( |Text 10 added at { utclong_current( ) } (using oref3)| ). DATA(oref4) = lcl_singleton=>get_obj( ). oref4->get_timestamps( IMPORTING ts_static = ts_static ts_instance = ts_instance ). APPEND VALUE #( name = `oref4` timestamp_static = ts_static timestamp_instance = ts_instance ) TO ts_tab. oref4->add_log( |Text 11 added at { utclong_current( ) } (using oref4)| ). oref4->add_log( |Text 12 added at { utclong_current( ) } (using oref4)| ). "Retrieving the content of the log table per object "However, as it is one and the same object that is dealt with, the content is the same. DATA(log1) = oref1->get_log( ). DATA(log2) = oref2->get_log( ). DATA(log3) = oref3->get_log( ). out->write( log1 ). out->write( |\n| ). ASSERT log1 = log2. ASSERT log1 = log3. "Displaying the time stamps visualizing the singleton pattern SORT ts_tab BY name ASCENDING. out->write( ts_tab ). ENDMETHOD. ENDCLASS. ``` |
| CCIMP include (Local Types tab in ADT) | ``` abap CLASS lcl_singleton DEFINITION CREATE PRIVATE. PUBLIC SECTION. CLASS-METHODS get_obj RETURNING VALUE(obj) TYPE REF TO lcl_singleton. METHODS add_log IMPORTING text TYPE string. METHODS get_log RETURNING VALUE(log) TYPE string_table. METHODS get_timestamps EXPORTING ts_static TYPE utclong ts_instance TYPE utclong. CLASS-METHODS class_constructor. METHODS constructor. PROTECTED SECTION. PRIVATE SECTION. CLASS-DATA oref TYPE REF TO lcl_singleton. CLASS-DATA log_table TYPE string_table. CLASS-DATA timestamp_static TYPE utclong. DATA timestamp_instance TYPE utclong. ENDCLASS. CLASS lcl_singleton IMPLEMENTATION. METHOD get_obj. IF oref IS NOT BOUND. oref = NEW lcl_singleton( ). ENDIF. obj = oref. ENDMETHOD. METHOD add_log. INSERT text INTO TABLE log_table. ENDMETHOD. METHOD get_log. log = log_table. ENDMETHOD. METHOD get_timestamps. ts_static = timestamp_static. ts_instance = timestamp_instance. ENDMETHOD. METHOD class_constructor. timestamp_static = utclong_current( ). ENDMETHOD. METHOD constructor. timestamp_instance = utclong_current( ). ENDMETHOD. ENDCLASS. ``` |
| Class include | Code |
| Global class | ``` abap CLASS zcl_demo_abap DEFINITION PUBLIC FINAL CREATE PUBLIC . PUBLIC SECTION. INTERFACES if_oo_adt_classrun. PROTECTED SECTION. PRIVATE SECTION. ENDCLASS. CLASS zcl_demo_abap IMPLEMENTATION. METHOD if_oo_adt_classrun~main. *&---------------------------------------------------------------------* *& Example 1 *&---------------------------------------------------------------------* "Adding strings "Retrieving the resulting string using the attribute 'str' DATA(str1) = lcl_string=>string( `Lorem` )->add( ` ` )->add( `ipsum` )->str. "Instead of extra method calls using the reference variable DATA(str1b_ref) = lcl_string=>string( `Lorem` ). str1b_ref->add( ` ` ). str1b_ref->add( `ipsum` ). DATA(str1b) = str1b_ref->str. "Retrieving the resulting string using the method 'get_string' DATA(str2) = lcl_string=>string( `Lorem` )->add( ` ` )->add( `ipsum` )->add( ` ` )->add( `dolor` )->add( ` ` )->add( `sit` )->add( ` ` )->add( `amet` )->get_string( ). "Preceding strings DATA(str3) = lcl_string=>string( `world` )->precede( ` ` )->precede( `Hello` )->str. DATA(str4) = lcl_string=>string( `B` )->add( `A` )->precede( `A` )->add( `P` )->str. "Splitting into string table DATA(tab1) = lcl_string=>string( `Lorem` )->add( `#` )->add( `ipsum` )->add( `#` )->add( `dolor` )->add( `#` )->add( `sit` )->add( `#` )->add( `amet` )->split_into_table( `#` ). DATA(tab2) = lcl_string=>string( `Lorem` )->add( ` ` )->add( `ipsum` )->split_into_table( ` ` ). "Replacements DATA(str5) = lcl_string=>string( `Lorem#ipsum#dolor#sit#amet` )->replace_all( sub = `#` with = ` ` )->str. DATA(str6) = lcl_string=>string( `Lorem#ipsum#dolor#sit#amet` )->replace_occ( sub = `#` with = ` ` occ = 1 )->str. DATA(str7) = lcl_string=>string( `Lorem#ipsum#dolor#sit#amet` )->replace_occ( sub = `#` with = ` ` occ = 2 )->str. DATA(str8) = lcl_string=>string( `Lorem#ipsum#dolor#sit#amet` )->replace_occ( sub = `#` with = ` ` occ = -2 )->str. DATA(tab3) = lcl_string=>string( `hello` )->add( `#` )->add( `world` )->replace_all( sub = `#` with = `,` )->split_into_table( `,` ). "Transforming to lowercase and uppercase DATA(str9) = lcl_string=>string( `ab` )->add( `ap` )->uppercase( )->str. DATA(str10) = lcl_string=>string( `AP` )->precede( `AB` )->lowercase( )->str. DATA(str11) = lcl_string=>string( `AB` )->lowercase( )->add( `ap` )->uppercase( )->str. "First lowercasing overridden "Reversing string DATA(str12) = lcl_string=>string( `OLL` )->add( `AH` )->lowercase( )->reverse_string( )->str. "Inserting string DATA(str13) = lcl_string=>string( `abcghi` )->insert_string( string = `def` off = 3 )->str. DATA(str14) = lcl_string=>string( `vwxyz` )->insert_string( string = `stu` off = 0 )->str. "Removing spaces "All spaces DATA(str15) = lcl_string=>string( ` a b c` )->add( ` d e f gh i ` )->remove_all_spaces( )->str. "Leading and trailing spaces DATA(str16) = lcl_string=>string( ` ab c d e f g h i ` )->remove_leading_trailing_spaces( )->str. DATA(str17) = lcl_string=>string( `abc ` )->remove_leading_trailing_spaces( )->add( `def` )->str. "Displaying results in the console out->write( data = str1 name = `str1` ). out->write( |\n| ). out->write( data = str1b name = `str1b` ). out->write( |\n| ). out->write( data = str2 name = `str2` ). out->write( |\n| ). out->write( data = str3 name = `str3` ). out->write( |\n| ). out->write( data = str4 name = `str4` ). out->write( |\n| ). out->write( data = tab1 name = `tab1` ). out->write( |\n| ). out->write( data = tab2 name = `tab2` ). out->write( |\n| ). out->write( data = str5 name = `str5` ). out->write( |\n| ). out->write( data = str6 name = `str6` ). out->write( |\n| ). out->write( data = str7 name = `str7` ). out->write( |\n| ). out->write( data = str8 name = `str8` ). out->write( |\n| ). out->write( data = tab3 name = `tab3` ). out->write( |\n| ). out->write( data = str9 name = `str9` ). out->write( |\n| ). out->write( data = str10 name = `str10` ). out->write( |\n| ). out->write( data = str11 name = `str11` ). out->write( |\n| ). out->write( data = str12 name = `str12` ). out->write( |\n| ). out->write( data = str13 name = `str13` ). out->write( |\n| ). out->write( data = str14 name = `str14` ). out->write( |\n| ). out->write( data = str15 name = `str15` ). out->write( |\n| ). out->write( data = str16 name = `str16` ). out->write( |\n| ). out->write( data = str17 name = `str17` ). out->write( |\n| ). ********************************************************************** *&---------------------------------------------------------------------* *& Example 2 *&---------------------------------------------------------------------* DATA(calc1) = NEW lcl_calc( 1 )->plus( 2 )->get_result( ). DATA(calc2) = NEW lcl_calc( 1 )->minus( 2 )->get_result( ). DATA(calc3) = NEW lcl_calc( 5 )->plus( 2 )->minus( 1 )->multiply( 3 )->get_result( ). DATA(calc4) = NEW lcl_calc( 10 )->multiply( 10 )->divide( 2 )->get_result( ). DATA(calc5) = NEW lcl_calc( 0 )->plus( 1 )->divide( 5 )->get_result( ). DATA(calc6) = NEW lcl_calc( '1.2' )->plus( '1.4' )->minus( '0.1' )->multiply( '2.5' )->divide( 2 )->get_result( ). "Arithmetic errors are just ignored in the example DATA(calc7) = NEW lcl_calc( 1 )->divide( 0 )->plus( 1 )->get_result( ). "Method chaining with a standalone statements NEW lcl_calc( 1 )->plus( 2 )->multiply( 5 )->minus( 5 )->divide( 2 )->get_result( RECEIVING result = DATA(calc8) ). IF NEW lcl_calc( 1 )->plus( 2 )->minus( 3 )->plus( 4 )->minus( 5 )->get_result( ) <= 0. DATA(if_statement) = `The result is equal to or lower than 0`. ELSE. if_statement = `The result is greater than 0`. ENDIF. out->write( data = calc1 name = `calc1` ). out->write( |\n| ). out->write( data = calc2 name = `calc2` ). out->write( |\n| ). out->write( data = calc3 name = `calc3` ). out->write( |\n| ). out->write( data = calc3 name = `calc3` ). out->write( |\n| ). out->write( data = calc4 name = `calc4` ). out->write( |\n| ). out->write( data = calc5 name = `calc5` ). out->write( |\n| ). out->write( data = calc6 name = `calc6` ). out->write( |\n| ). out->write( data = calc7 name = `calc7` ). out->write( |\n| ). out->write( data = calc8 name = `calc8` ). out->write( |\n| ). out->write( data = if_statement name = `if_statement` ). ENDMETHOD. ENDCLASS. ``` |
| CCIMP include (Local Types tab in ADT) | ``` abap *&---------------------------------------------------------------------* *& Example 1 *&---------------------------------------------------------------------* INTERFACE lif_string_processing. DATA str TYPE string READ-ONLY. METHODS add IMPORTING string TYPE clike RETURNING VALUE(ref) TYPE REF TO lif_string_processing. METHODS precede IMPORTING string TYPE clike RETURNING VALUE(ref) TYPE REF TO lif_string_processing. METHODS replace_all IMPORTING sub TYPE clike with TYPE clike RETURNING VALUE(ref) TYPE REF TO lif_string_processing. METHODS replace_occ IMPORTING sub TYPE clike with TYPE clike occ TYPE i DEFAULT 1 RETURNING VALUE(ref) TYPE REF TO lif_string_processing. METHODS lowercase RETURNING VALUE(ref) TYPE REF TO lif_string_processing. METHODS uppercase RETURNING VALUE(ref) TYPE REF TO lif_string_processing. METHODS remove_leading_trailing_spaces RETURNING VALUE(ref) TYPE REF TO lif_string_processing. METHODS remove_all_spaces RETURNING VALUE(ref) TYPE REF TO lif_string_processing. METHODS reverse_string RETURNING VALUE(ref) TYPE REF TO lif_string_processing. METHODS insert_string IMPORTING string TYPE clike off TYPE i RETURNING VALUE(ref) TYPE REF TO lif_string_processing. METHODS get_string RETURNING VALUE(str) TYPE string. METHODS split_into_table IMPORTING split_at TYPE clike RETURNING VALUE(tab) TYPE string_table. ENDINTERFACE. CLASS lcl_string DEFINITION DEFERRED. CLASS lcl_string_processing DEFINITION FINAL CREATE PRIVATE FRIENDS lcl_string. PUBLIC SECTION. INTERFACES lif_string_processing. ALIASES: add FOR lif_string_processing~add, get_string FOR lif_string_processing~get_string, insert_string FOR lif_string_processing~insert_string, precede FOR lif_string_processing~precede, remove_all_spaces FOR lif_string_processing~remove_all_spaces, remove_leading_trailing_spaces FOR lif_string_processing~remove_leading_trailing_spaces, replace_all FOR lif_string_processing~replace_all, replace_occ FOR lif_string_processing~replace_occ, reverse_string FOR lif_string_processing~reverse_string, split_into_table FOR lif_string_processing~split_into_table, lowercase FOR lif_string_processing~lowercase, uppercase FOR lif_string_processing~uppercase. PROTECTED SECTION. PRIVATE SECTION. ALIASES string_content FOR lif_string_processing~str. METHODS constructor IMPORTING content TYPE string. DATA oref TYPE REF TO lcl_string_processing. ENDCLASS. CLASS lcl_string_processing IMPLEMENTATION. METHOD add. oref->string_content &&= string. ref = oref. ENDMETHOD. METHOD get_string. str = oref->string_content. ENDMETHOD. METHOD insert_string. TRY. oref->string_content = insert( val = oref->string_content sub = string off = off ). CATCH cx_sy_range_out_of_bounds. ENDTRY. ref = oref. ENDMETHOD. METHOD precede. oref->string_content = string && oref->string_content. ref = oref. ENDMETHOD. METHOD remove_all_spaces. oref->string_content = condense( val = oref->string_content to = `` ). ref = oref. ENDMETHOD. METHOD remove_leading_trailing_spaces. oref->string_content = condense( val = oref->string_content from = `` ). ref = oref. ENDMETHOD. METHOD replace_all. oref->string_content = replace( val = oref->string_content sub = sub with = with occ = 0 ). ref = oref. ENDMETHOD. METHOD replace_occ. oref->string_content = replace( val = oref->string_content sub = sub with = with occ = occ ). ref = oref. ENDMETHOD. METHOD reverse_string. oref->string_content = reverse( oref->string_content ). ref = oref. ENDMETHOD. METHOD split_into_table. SPLIT oref->string_content AT split_at INTO TABLE tab. ENDMETHOD. METHOD lowercase. oref->string_content = to_lower( oref->string_content ). ref = oref. ENDMETHOD. METHOD uppercase. oref->string_content = to_upper( oref->string_content ). ref = oref. ENDMETHOD. METHOD constructor. string_content = content. oref = me. ENDMETHOD. ENDCLASS. CLASS lcl_string DEFINITION FINAL CREATE PRIVATE FRIENDS lcl_string_processing. PUBLIC SECTION. CLASS-METHODS string IMPORTING string TYPE clike RETURNING VALUE(ref) TYPE REF TO lif_string_processing. PROTECTED SECTION. PRIVATE SECTION. ENDCLASS. CLASS lcl_string IMPLEMENTATION. METHOD string. ref = NEW lcl_string_processing( string ). ENDMETHOD. ENDCLASS. ********************************************************************** *&---------------------------------------------------------------------* *& Example 2 *&---------------------------------------------------------------------* CLASS lcl_calc DEFINITION FINAL CREATE PUBLIC. PUBLIC SECTION. METHODS constructor IMPORTING num TYPE decfloat34. METHODS plus IMPORTING num TYPE decfloat34 RETURNING VALUE(ref) TYPE REF TO lcl_calc. METHODS minus IMPORTING num TYPE decfloat34 RETURNING VALUE(ref) TYPE REF TO lcl_calc. METHODS multiply IMPORTING num TYPE decfloat34 RETURNING VALUE(ref) TYPE REF TO lcl_calc. METHODS divide IMPORTING num TYPE decfloat34 RETURNING VALUE(ref) TYPE REF TO lcl_calc. METHODS get_result RETURNING VALUE(result) TYPE decfloat34. PROTECTED SECTION. PRIVATE SECTION. DATA number TYPE decfloat34. ENDCLASS. CLASS lcl_calc IMPLEMENTATION. METHOD constructor. number = num. ENDMETHOD. METHOD divide. TRY. number /= num. CATCH cx_sy_arithmetic_error. ENDTRY. ref = me. ENDMETHOD. METHOD minus. TRY. number -= num. CATCH cx_sy_arithmetic_error. ENDTRY. ref = me. ENDMETHOD. METHOD multiply. TRY. number *= num. CATCH cx_sy_arithmetic_error. ENDTRY. ref = me. ENDMETHOD. METHOD plus. TRY. number += num. CATCH cx_sy_arithmetic_error. ENDTRY. ref = me. ENDMETHOD. METHOD get_result. result = number. ENDMETHOD. ENDCLASS. ``` |
| Class include | Code |
| Global class | ``` abap CLASS zcl_demo_abap DEFINITION PUBLIC FINAL CREATE PUBLIC . PUBLIC SECTION. INTERFACES if_oo_adt_classrun. PROTECTED SECTION. PRIVATE SECTION. ENDCLASS. CLASS zcl_demo_abap IMPLEMENTATION. METHOD if_oo_adt_classrun~main. "Saying hello in English DATA(oref_en) = lcl_hello_factory=>create_hello( lif_hello=>en ). DATA(hello_en) = oref_en->say_hello( ). out->write( hello_en ). "Saying hello in French DATA(oref_fr) = lcl_hello_factory=>create_hello( lif_hello=>fr ). DATA(hello_fr) = oref_fr->say_hello( ). out->write( hello_fr ). "Saying hello in Italian DATA(oref_it) = lcl_hello_factory=>create_hello( lif_hello=>it ). DATA(hello_it) = oref_it->say_hello( ). out->write( hello_it ). "Saying hello in Spanish DATA(oref_es) = lcl_hello_factory=>create_hello( lif_hello=>es ). DATA(hello_es) = oref_es->say_hello( ). out->write( hello_es ). "Saying hello in German "See the local class implementation. This method call demonstrates the adapter since "the required data is originally available in a non-conform way ('Hallo' is "available as xstring, coming from a different API that does not implement the same "interface as the other classes). The adapter class (called when creating the instance "in the factory method) integrates the non-conform API and transforms the content. DATA(oref_de) = lcl_hello_factory=>create_hello( lif_hello=>de ). DATA(hello_de) = oref_de->say_hello( ). out->write( hello_de ). "Default hello DATA(oref_default) = lcl_hello_factory=>create_hello( lif_hello=>init ). DATA(hello_default) = oref_default->say_hello( ). out->write( hello_default ). ENDMETHOD. ENDCLASS. ``` |
| CCIMP include (Local Types tab in ADT) | ``` abap INTERFACE lif_hello. TYPES: basetype TYPE i, BEGIN OF ENUM enum_langu BASE TYPE basetype, init VALUE IS INITIAL, en VALUE 1, fr VALUE 2, it VALUE 3, es VALUE 4, de VALUE 5, END OF ENUM enum_langu. METHODS say_hello RETURNING VALUE(hi) TYPE string. ENDINTERFACE. CLASS lcl_en DEFINITION FINAL CREATE PUBLIC. PUBLIC SECTION. INTERFACES lif_hello. PROTECTED SECTION. PRIVATE SECTION. ENDCLASS. CLASS lcl_en IMPLEMENTATION. METHOD lif_hello~say_hello. hi = `Hi`. ENDMETHOD. ENDCLASS. CLASS lcl_fr DEFINITION FINAL CREATE PUBLIC. PUBLIC SECTION. INTERFACES lif_hello. PROTECTED SECTION. PRIVATE SECTION. ENDCLASS. CLASS lcl_fr IMPLEMENTATION. METHOD lif_hello~say_hello. hi = `Salut`. ENDMETHOD. ENDCLASS. CLASS lcl_it DEFINITION FINAL CREATE PUBLIC. PUBLIC SECTION. INTERFACES lif_hello. PROTECTED SECTION. PRIVATE SECTION. ENDCLASS. CLASS lcl_it IMPLEMENTATION. METHOD lif_hello~say_hello. hi = `Ciao`. ENDMETHOD. ENDCLASS. CLASS lcl_es DEFINITION FINAL CREATE PUBLIC. PUBLIC SECTION. INTERFACES lif_hello. PROTECTED SECTION. PRIVATE SECTION. ENDCLASS. CLASS lcl_es IMPLEMENTATION. METHOD lif_hello~say_hello. hi = `Hola`. ENDMETHOD. ENDCLASS. ********************************************************************** "Class that does not implement the lif_hello interface "The assumption is that functionality of the API is reused and integrated "into the exsisting API. The non-compatible type is converted using an "adapter class. INTERFACE lif_hello_as_xstring. METHODS xstring_hello RETURNING VALUE(hi) TYPE xstring. ENDINTERFACE. CLASS lcl_de_xstring DEFINITION FINAL CREATE PUBLIC. PUBLIC SECTION. INTERFACES lif_hello_as_xstring. PROTECTED SECTION. PRIVATE SECTION. ENDCLASS. CLASS lcl_de_xstring IMPLEMENTATION. METHOD lif_hello_as_xstring~xstring_hello. hi = CONV xstring( `48616C6C6F` ). ENDMETHOD. ENDCLASS. ********************************************************************** "Adapter class CLASS lcl_de_adapter DEFINITION. PUBLIC SECTION. INTERFACES: lif_hello. ENDCLASS. CLASS lcl_de_adapter IMPLEMENTATION. METHOD lif_hello~say_hello. DATA(oref) = NEW lcl_de_xstring( ). DATA(hello_as_xstring) = oref->lif_hello_as_xstring~xstring_hello( ). hi = cl_abap_conv_codepage=>create_in( )->convert( hello_as_xstring ). ENDMETHOD. ENDCLASS. ********************************************************************** "Class containing a factory method CLASS lcl_hello_factory DEFINITION FINAL CREATE PRIVATE. PUBLIC SECTION. CLASS-METHODS create_hello IMPORTING language TYPE lif_hello=>enum_langu RETURNING VALUE(hello) TYPE REF TO lif_hello. PROTECTED SECTION. PRIVATE SECTION. ENDCLASS. CLASS lcl_hello_factory IMPLEMENTATION. METHOD create_hello. hello = SWITCH #( language WHEN lif_hello=>en THEN NEW lcl_en( ) WHEN lif_hello=>fr THEN NEW lcl_fr( ) WHEN lif_hello=>it THEN NEW lcl_it( ) WHEN lif_hello=>es THEN NEW lcl_es( ) "Calling the method in the adapter class WHEN lif_hello=>de THEN NEW lcl_de_adapter( ) "E.g. raising an exception or returning a default object ELSE NEW lcl_en( ) ). ENDMETHOD. ENDCLASS. ``` |
| Class include | Code |
| Global class |
``` abap
"! ABAP example demonstrating the builder design pattern
"! See the disclaimer in the ABAP cheat sheet repository's readme file.
CLASS zcl_demo_abap DEFINITION
PUBLIC
FINAL
CREATE PUBLIC .
PUBLIC SECTION.
INTERFACES if_oo_adt_classrun.
CLASS-METHODS get_table_info IMPORTING itab TYPE ANY TABLE RETURNING VALUE(info) TYPE string_table.
PROTECTED SECTION.
PRIVATE SECTION.
ENDCLASS.
CLASS zcl_demo_abap IMPLEMENTATION.
METHOD if_oo_adt_classrun~main.
"Creating a string table that includes type names
"The entries include database table, CDS entity names of the ABAP cheat sheet repository.
"Plus, elementary types (built-in ABAP types) and a non-existent type are included.
DATA(type_names) = VALUE string_table(
( `ZDEMO_ABAP_CARR` )
( `ZDEMO_ABAP_FLI` )
( `ZDEMO_ABAP_CARR_VE` )
( `ZDEMO_ABAP_ABSTRACT_ENT` )
"Elementary types
( `STRING` )
( `UTCLONG` )
"Non-existent type
( `TYPE_THAT_DOES_NOT_EXIST` ) ).
out->write( `1) Creating standard tables with non-unique primary table keys` ).
out->write( |\n| ).
"Specifying no key components, using default ones
LOOP AT type_names INTO DATA(name).
DATA(oref) = lcl_itab_provider=>create_itab(
type_name = name
table_kind = lcl_itab_provider=>standard_w_nonunique_pr_key
table_entry_count = 10 ).
out->write( |------------- Table with line type { oref->type_name } -------------| ).
out->write( |\n| ).
IF oref->type_exists = abap_true.
"The example is designed to retrieve Table type informationrmation so as to display
"information such type and table keys of the internal table.
DATA(info) = get_table_info( oref->itab->* ).
out->write( `Table type information:` ).
out->write( info ).
out->write( |\n| ).
out->write( oref->itab->* ).
out->write( |\n| ).
ELSE.
out->write( `Type does not exist. Internal table not created.` ).
out->write( |\n| ).
ENDIF.
ENDLOOP.
out->write( `------------- Key components explicitly specified -------------` ).
out->write( |\n| ).
"Key components explicitly specified (including a non-existent component name that is ignored)
DATA(oref_key_specified) = lcl_itab_provider=>create_itab(
type_name = `ZDEMO_ABAP_CARR`
table_kind = lcl_itab_provider=>standard_w_nonunique_pr_key
key_components = VALUE #( ( `CARRID` ) ( `CARRNAME` ) ( `FALSE_COMPONENT` ) )
table_entry_count = 3 ).
out->write( `------------- Table with line type ZDEMO_ABAP_CARR -------------` ).
IF oref_key_specified->type_exists = abap_true.
info = get_table_info( oref_key_specified->itab->* ).
out->write( `Table type information:` ).
out->write( info ).
out->write( |\n| ).
out->write( oref_key_specified->itab->* ).
out->write( |\n| ).
ELSE.
out->write( `Type does not exist. Internal table not created.` ).
out->write( |\n| ).
ENDIF.
out->write( repeat( val = `*` occ = 100 ) ).
out->write( |\n| ).
**********************************************************************
out->write( `2) Creating standard tables with empty key` ).
out->write( |\n| ).
type_names = VALUE string_table(
( `ZDEMO_ABAP_FLSCH` )
( `D` ) ).
LOOP AT type_names INTO name.
DATA(oref_empty_key) = lcl_itab_provider=>create_itab(
type_name = name
table_kind = lcl_itab_provider=>standard_w_empty_key
"Specified key components are ignored in the example
"key_components = VALUE #( ( `CARRID` ) ( `CARRNAME` ) )
table_entry_count = 3 ).
out->write( |------------- Table with line type { oref_empty_key->type_name } -------------| ).
out->write( |\n| ).
IF oref_empty_key->type_exists = abap_true.
info = get_table_info( oref_empty_key->itab->* ).
out->write( `Table type information:` ).
out->write( info ).
out->write( |\n| ).
out->write( oref_empty_key->itab->* ).
out->write( |\n| ).
ELSE.
out->write( `Type does not exist. Internal table not created.` ).
out->write( |\n| ).
ENDIF.
ENDLOOP.
out->write( repeat( val = `*` occ = 100 ) ).
out->write( |\n| ).
**********************************************************************
out->write( `3) Creating sorted tables with unique primary keys` ).
out->write( |\n| ).
type_names = VALUE string_table(
( `ZDEMO_ABAP_FLI` )
( `ZDEMO_ABAP_TAB1` )
( `T` ) ).
LOOP AT type_names INTO name.
DATA(oref_sorted) = lcl_itab_provider=>create_itab(
type_name = name
table_kind = lcl_itab_provider=>sorted_w_unique_pr_key
table_entry_count = 3 ).
out->write( |------------- Table with line type { oref_sorted->type_name } -------------| ).
out->write( |\n| ).
IF oref_sorted->type_exists = abap_true.
info = get_table_info( oref_sorted->itab->* ).
out->write( `Table type information:` ).
out->write( info ).
out->write( |\n| ).
out->write( oref_sorted->itab->* ).
out->write( |\n| ).
ELSE.
out->write( `Type does not exist. Internal table not created.` ).
out->write( |\n| ).
ENDIF.
ENDLOOP.
out->write( repeat( val = `*` occ = 100 ) ).
out->write( |\n| ).
**********************************************************************
out->write( `4) Creating hashed tables with unique primary keys` ).
out->write( |\n| ).
type_names = VALUE string_table(
( `ZDEMO_ABAP_CARR` )
( `ZDEMO_ABAP_TAB2` )
( `I` ) ).
LOOP AT type_names INTO name.
DATA(oref_hashed) = lcl_itab_provider=>create_itab(
type_name = name
table_kind = lcl_itab_provider=>hashed_w_unique_pr_key
table_entry_count = 3 ).
out->write( |------------- Table with line type { oref_hashed->type_name } -------------| ).
out->write( |\n| ).
IF oref_hashed->type_exists = abap_true.
info = get_table_info( oref_hashed->itab->* ).
out->write( `Table type information:` ).
out->write( info ).
out->write( |\n| ).
out->write( oref_hashed->itab->* ).
out->write( |\n| ).
ELSE.
out->write( `Type does not exist. Internal table not created.` ).
out->write( |\n| ).
ENDIF.
ENDLOOP.
out->write( repeat( val = `*` occ = 100 ) ).
out->write( |\n| ).
**********************************************************************
out->write( `5) Populating internal tables with random data` ).
out->write( |\n| ).
"Demo internal tables to be filled
DATA it_std1 TYPE TABLE OF zdemo_abap_carr WITH EMPTY KEY.
DATA it_std2 TYPE string_table.
DATA it_std3 TYPE TABLE OF i.
TYPES: BEGIN OF various_types,
c1 TYPE c LENGTH 1,
c5 TYPE c LENGTH 5,
c10 TYPE c LENGTH 10,
str TYPE string,
int TYPE i,
f TYPE f,
dec16 TYPE decfloat16,
dec34 TYPE decfloat34,
i8 TYPE int8,
n5 TYPE n LENGTH 5,
time TYPE t,
date TYPE d,
timestamp TYPE utclong,
x1 TYPE x LENGTH 1,
x5 TYPE x LENGTH 5,
xstr TYPE xstring,
pl2d1 TYPE p LENGTH 2 DECIMALS 1,
pl3d2 TYPE p LENGTH 3 DECIMALS 2,
pl4d3 TYPE p LENGTH 4 DECIMALS 3,
pl5d4 TYPE p LENGTH 5 DECIMALS 4,
pl6d5 TYPE p LENGTH 6 DECIMALS 5,
pl7d6 TYPE p LENGTH 7 DECIMALS 6,
pl8d7 TYPE p LENGTH 8 DECIMALS 7,
pl9d8 TYPE p LENGTH 9 DECIMALS 8,
pl10d9 TYPE p LENGTH 10 DECIMALS 9,
pl11d10 TYPE p LENGTH 11 DECIMALS 10,
pl12d11 TYPE p LENGTH 12 DECIMALS 11,
pl13d12 TYPE p LENGTH 13 DECIMALS 12,
pl14d13 TYPE p LENGTH 14 DECIMALS 13,
pl15d14 TYPE p LENGTH 15 DECIMALS 14,
END OF various_types.
DATA it_std4 TYPE TABLE OF various_types WITH EMPTY KEY.
"Sorted tables
DATA it_sorted1 TYPE SORTED TABLE OF zdemo_abap_flsch WITH NON-UNIQUE KEY primary_key COMPONENTS carrid connid cityfrom.
DATA it_sorted2 TYPE SORTED TABLE OF zdemo_abap_fli WITH UNIQUE KEY carrid connid.
DATA it_sorted3 TYPE SORTED TABLE OF utclong WITH NON-UNIQUE KEY table_line.
"Hashed tables
DATA it_hashed1 TYPE HASHED TABLE OF zdemo_abap_flsch WITH UNIQUE KEY primary_key COMPONENTS carrid connid.
TYPES n5 TYPE n LENGTH 5.
DATA it_hashed2 TYPE HASHED TABLE OF n5 WITH UNIQUE KEY primary_key COMPONENTS table_line.
TYPES table_refs TYPE TABLE OF REF TO data WITH EMPTY KEY.
DATA(itab_refs) = VALUE table_refs(
( REF #( it_std1 ) )
( REF #( it_std2 ) )
( REF #( it_std3 ) )
( REF #( it_std4 ) )
( REF #( it_sorted1 ) )
( REF #( it_sorted2 ) )
( REF #( it_sorted3 ) )
( REF #( it_hashed1 ) )
( REF #( it_hashed2 ) ) ).
LOOP AT itab_refs INTO DATA(ref).
DATA(tabix) = sy-tabix.
DATA(oref_populate_itab) = lcl_itab_provider=>populate_itab(
itab = ref->*
table_entry_count = 3
).
out->write( |------------- Internal table { tabix } -------------| ).
out->write( |\n| ).
info = get_table_info( oref_populate_itab->itab->* ).
out->write( `Table type information:` ).
out->write( info ).
out->write( |\n| ).
out->write( oref_populate_itab->itab->* ).
out->write( |\n| ).
ENDLOOP.
out->write( repeat( val = `*` occ = 100 ) ).
out->write( |\n| ).
**********************************************************************
out->write( `6) Other line types` ).
out->write( |\n| ).
"Other line types not supported in the example
*DATA(oref_not_working) = lcl_itab_provider=>populate_itab(
* itab = itab_refs
* table_entry_count = 3 ).
"Deep/nested line types are not supported
"These components remain initial.
TYPES: BEGIN OF deep_type,
flag TYPE abap_boolean,
c5 TYPE c LENGTH 5,
strtab TYPE string_table,
struc TYPE zdemo_abap_carr,
END OF deep_type.
DATA deep_itab TYPE TABLE OF deep_type WITH EMPTY KEY.
DATA(oref_deep) = lcl_itab_provider=>populate_itab(
itab = deep_itab
table_entry_count = 3 ).
out->write( oref_deep->itab->* ).
out->write( |\n| ).
out->write( repeat( val = `*` occ = 100 ) ).
out->write( |\n| ).
**********************************************************************
out->write( `7) Exploring the random value creation methods` ).
out->write( |\n| ).
out->write( `---------------- Getting random strings ----------------` ).
DO 5 TIMES.
DATA(str) = lcl_itab_builder=>get_random_string( sy-index ).
out->write( str ).
ENDDO.
out->write( `---------------- Getting random number sequences ----------------` ).
DO 5 TIMES.
DATA(number_set) = lcl_itab_builder=>get_random_number_sequence( sy-index ).
out->write( number_set ).
ENDDO.
out->write( `---------------- Getting random packed numbers ----------------` ).
DO 15 TIMES.
DATA(random_p) = lcl_itab_builder=>get_random_p(
length = 8
decimals = sy-index - 1 ).
out->write( random_p->* ).
ENDDO.
out->write( `---------------- Getting random dates ----------------` ).
DO 5 TIMES.
DATA(random_d) = lcl_itab_builder=>get_random_d( ).
out->write( random_d ).
ENDDO.
out->write( `---------------- Getting random times ----------------` ).
DO 5 TIMES.
DATA(random_t) = lcl_itab_builder=>get_random_t( ).
out->write( random_t ).
ENDDO.
out->write( `---------------- Getting random UTC timestamps ----------------` ).
DO 5 TIMES.
DATA(random_utc) = lcl_itab_builder=>get_random_utclong( ).
out->write( random_utc ).
ENDDO.
out->write( `---------------- Getting random data objects of type decfloat16 ----------------` ).
DO 5 TIMES.
DATA(random_dec16) = lcl_itab_builder=>get_random_dec16( ).
out->write( random_dec16 ).
ENDDO.
out->write( `---------------- Getting random data objects of type decfloat34 ----------------` ).
DO 5 TIMES.
DATA(random_dec34) = lcl_itab_builder=>get_random_dec34( ).
out->write( random_dec34 ).
ENDDO.
out->write( `---------------- Getting random data objects of type f ----------------` ).
DO 5 TIMES.
DATA(random_f) = lcl_itab_builder=>get_random_f( ).
out->write( random_f ).
ENDDO.
out->write( `---------------- Getting random data objects of type x ----------------` ).
DATA(xstr_1) = lcl_itab_builder=>get_random_x( 1 ).
DATA x1 TYPE x LENGTH 1.
x1 = xstr_1.
out->write( x1 ).
DATA(xstr_2) = lcl_itab_builder=>get_random_x( 2 ).
DATA x2 TYPE x LENGTH 2.
x2 = xstr_2.
out->write( x2 ).
DATA(xstr_8) = lcl_itab_builder=>get_random_x( 8 ).
DATA x8 TYPE x LENGTH 8.
x8 = xstr_8.
out->write( x8 ).
out->write( `---------------- Getting random data objects of type xstring ----------------` ).
DATA(xstr_a) = lcl_itab_builder=>get_random_xstring( ).
out->write( xstr_a ).
DATA(xstr_b) = lcl_itab_builder=>get_random_xstring( ).
out->write( xstr_b ).
DATA(xstr_c) = lcl_itab_builder=>get_random_xstring( ).
out->write( xstr_c ).
ENDMETHOD.
METHOD get_table_info.
DATA(tab_type_info) = CAST cl_abap_tabledescr( cl_abap_typedescr=>describe_by_data( itab ) ).
"Getting the table kind
"For the constant values of type abap_tablekind, see cl_abap_tabledescr. For example, 'S'
"stands for a standard table.
DATA(tab_table_kind) = tab_type_info->table_kind.
INSERT |Table kind: { tab_table_kind }| INTO TABLE info.
"Checking if the table has a unique key
DATA(tab_has_unique_key) = tab_type_info->has_unique_key.
INSERT |Has a unique key: "{ tab_has_unique_key }" | &&
|{ COND #( WHEN tab_has_unique_key IS INITIAL THEN `(no unique key)` ) }| INTO TABLE info.
"Returning a table with a description of all table keys, e.g. all components of a key,
"key kind (U, unique, in the example case), information whether the key is the primary
"key etc. For the constant values, see the cl_abap_tabledescr class.
DATA(tab_keys) = tab_type_info->get_keys( ).
INSERT |Table keys: { REDUCE string( INIT str = `` FOR |
| CCIMP include (Local Types tab in ADT) |
``` abap
"Class for the builder
"An abstract class is used as there are more general tasks performed by the subclasses.
"These tasks are implemented in non-abstract methods in the class.
CLASS lcl_itab_builder DEFINITION ABSTRACT CREATE PUBLIC.
PUBLIC SECTION.
DATA type_name TYPE string.
DATA primary_key_components TYPE string_table.
DATA itab TYPE REF TO data.
DATA table_entries_to_create TYPE i.
DATA type_exists TYPE abap_boolean.
DATA components TYPE cl_abap_structdescr=>component_table.
DATA is_elementary_line_type TYPE abap_boolean.
DATA table_type_descr_obj TYPE REF TO cl_abap_tabledescr.
DATA line_type TYPE REF TO cl_abap_datadescr.
"----------------------- Abstract methods -----------------------
METHODS build_type_info ABSTRACT RETURNING VALUE(type_exists) TYPE abap_boolean.
METHODS build_components ABSTRACT.
METHODS build_table_keys ABSTRACT.
METHODS build_table_type ABSTRACT.
METHODS build_data_object ABSTRACT.
METHODS build_random_data ABSTRACT.
"----------------------- Constants used in non-abstract methods -----------------------
CONSTANTS character_set TYPE string VALUE `abcdefghijklmnopqrstuvwxyz0123456789`.
CONSTANTS number_set TYPE string VALUE `0123456789`.
CONSTANTS max_length TYPE i VALUE 10.
CONSTANTS start_date TYPE d VALUE '20250101'.
CONSTANTS start_time TYPE t VALUE '000000'.
CONSTANTS max_table_entry_count TYPE i VALUE 50.
CONSTANTS min_int_value TYPE i VALUE 1.
CONSTANTS max_int_value TYPE i VALUE 100.
CONSTANTS min_int8_value TYPE int8 VALUE 1.
CONSTANTS max_int8_value TYPE int8 VALUE 100.
CONSTANTS min_p_value TYPE p VALUE 0.
CONSTANTS max_p_value TYPE p VALUE 9.
"----------------------- Non-abstract methods used by subclasses -----------------------
"They are intentionally included in the public visibility section for the demo in the
"global class.
METHODS check_type.
METHODS handle_keys.
METHODS handle_components.
METHODS add_table_entries
IMPORTING
VALUE(table_entry_count) TYPE i.
CLASS-METHODS get_random_string
IMPORTING
length TYPE i OPTIONAL
randomize_length TYPE abap_boolean DEFAULT abap_true
PREFERRED PARAMETER length
RETURNING
VALUE(str) TYPE string.
CLASS-METHODS get_random_number_sequence
IMPORTING
length TYPE i OPTIONAL
randomize_length TYPE abap_boolean DEFAULT abap_true
PREFERRED PARAMETER length
RETURNING
VALUE(numbers) TYPE string.
CLASS-METHODS get_random_i
IMPORTING min_value TYPE i DEFAULT min_int_value
max_value TYPE i DEFAULT max_int_value
RETURNING VALUE(number) TYPE i.
CLASS-METHODS get_random_int8
IMPORTING min_value TYPE int8 DEFAULT min_int8_value
max_value TYPE int8 DEFAULT max_int8_value
RETURNING VALUE(number) TYPE i.
CLASS-METHODS get_random_p
IMPORTING length TYPE i
decimals TYPE i
min_value TYPE p DEFAULT min_p_value
max_value TYPE p DEFAULT max_p_value
RETURNING VALUE(packed_number) TYPE REF TO data.
CLASS-METHODS get_random_n
IMPORTING length TYPE i
RETURNING VALUE(random_n) TYPE string.
CLASS-METHODS get_random_d
RETURNING VALUE(random_d) TYPE d.
CLASS-METHODS get_random_t
RETURNING VALUE(random_t) TYPE t.
CLASS-METHODS get_random_utclong
RETURNING VALUE(random_utc) TYPE utclong.
CLASS-METHODS get_random_dec16
RETURNING VALUE(random_dec16) TYPE decfloat16.
CLASS-METHODS get_random_dec34
RETURNING VALUE(random_dec34) TYPE decfloat34.
CLASS-METHODS get_random_f
RETURNING VALUE(random_f) TYPE f.
CLASS-METHODS get_random_x
IMPORTING length TYPE i
RETURNING VALUE(random_x) TYPE xstring.
CLASS-METHODS get_random_xstring
RETURNING VALUE(random_xstring) TYPE xstring.
PROTECTED SECTION.
PRIVATE SECTION.
ENDCLASS.
CLASS lcl_itab_builder IMPLEMENTATION.
METHOD get_random_string.
IF length IS NOT SUPPLIED.
DATA(len) = cl_abap_random_int=>create( seed = cl_abap_random=>seed( )
min = 1
max = max_length )->get_next( ).
ELSE.
IF length NOT BETWEEN 1 AND max_length.
len = max_length.
ELSE.
len = length.
ENDIF.
IF randomize_length = abap_true.
len = cl_abap_random_int=>create( seed = cl_abap_random=>seed( )
min = 1
max = len )->get_next( ).
ENDIF.
ENDIF.
DO len TIMES.
DATA(num) = cl_abap_random_int=>create( seed = cl_abap_random=>seed( )
min = 0
max = strlen( character_set ) - 1 )->get_next( ).
str &&= character_set+num(1).
ENDDO.
ENDMETHOD.
METHOD get_random_number_sequence.
IF length IS NOT SUPPLIED.
DATA(len) = cl_abap_random_int=>create( seed = cl_abap_random=>seed( )
min = 1
max = max_length )->get_next( ).
ELSE.
IF length NOT BETWEEN 1 AND max_length.
len = max_length.
ELSE.
len = length.
ENDIF.
IF randomize_length = abap_true.
len = cl_abap_random_int=>create( seed = cl_abap_random=>seed( )
min = 1
max = len )->get_next( ).
ENDIF.
ENDIF.
DO len TIMES.
DATA(num) = cl_abap_random_int=>create( seed = cl_abap_random=>seed( )
min = 0
max = strlen( number_set ) - 1 )->get_next( ).
numbers &&= number_set+num(1).
ENDDO.
ENDMETHOD.
METHOD get_random_i.
RETURN cl_abap_random_int=>create( seed = cl_abap_random=>seed( )
min = min_value
max = max_value )->get_next( ).
ENDMETHOD.
METHOD get_random_int8.
RETURN cl_abap_random_int8=>create( seed = cl_abap_random=>seed( )
min = min_value
max = max_value )->get_next( ).
ENDMETHOD.
METHOD get_random_p.
IF length NOT BETWEEN 1 AND 16.
RETURN.
ENDIF.
IF decimals NOT BETWEEN 0 AND 14.
RETURN.
ENDIF.
TRY.
CASE decimals.
WHEN 0.
DATA(a) = cl_abap_random_packed=>create( seed = cl_abap_random=>seed( ) min = CONV cl_abap_random_packed=>p31_0( min_value ) max = CONV cl_abap_random_packed=>p31_0( max_value ) )->get_next( ).
CREATE DATA packed_number LIKE a.
packed_number->* = a.
WHEN 1.
DATA(b) = cl_abap_random_packed_dec1=>create( seed = cl_abap_random=>seed( )
min = COND #( WHEN length = 1 THEN CONV cl_abap_random_packed_dec1=>p31_1( '0.1' ) ELSE CONV cl_abap_random_packed_dec1=>p31_1( min_value ) )
max = COND #( WHEN length = 1 THEN CONV cl_abap_random_packed_dec1=>p31_1( '0.9' ) ELSE CONV cl_abap_random_packed_dec1=>p31_1( max_value ) )
)->get_next( ).
CREATE DATA packed_number LIKE b.
packed_number->* = b.
WHEN 2.
DATA(c) = cl_abap_random_packed_dec2=>create( seed = cl_abap_random=>seed( ) min = CONV cl_abap_random_packed_dec2=>p31_2( min_value ) max = CONV cl_abap_random_packed_dec2=>p31_2( max_value ) )->get_next( ).
CREATE DATA packed_number LIKE c.
packed_number->* = c.
WHEN 3.
DATA(d) = cl_abap_random_packed_dec3=>create( seed = cl_abap_random=>seed( ) min = CONV cl_abap_random_packed_dec3=>p31_3( min_value ) max = CONV cl_abap_random_packed_dec3=>p31_3( max_value ) )->get_next( ).
CREATE DATA packed_number LIKE d.
packed_number->* = d.
WHEN 4.
DATA(e) = cl_abap_random_packed_dec4=>create( seed = cl_abap_random=>seed( ) min = CONV cl_abap_random_packed_dec4=>p31_4( min_value ) max = CONV cl_abap_random_packed_dec4=>p31_4( max_value ) )->get_next( ).
CREATE DATA packed_number LIKE e.
packed_number->* = e.
WHEN 5.
DATA(f) = cl_abap_random_packed_dec5=>create( seed = cl_abap_random=>seed( ) min = CONV cl_abap_random_packed_dec5=>p31_5( min_value ) max = CONV cl_abap_random_packed_dec5=>p31_5( max_value ) )->get_next( ).
CREATE DATA packed_number LIKE f.
packed_number->* = f.
WHEN 6.
DATA(g) = cl_abap_random_packed_dec6=>create( seed = cl_abap_random=>seed( ) min = CONV cl_abap_random_packed_dec6=>p31_6( min_value ) max = CONV cl_abap_random_packed_dec6=>p31_6( max_value ) )->get_next( ).
CREATE DATA packed_number LIKE g.
packed_number->* = g.
WHEN 7.
DATA(h) = cl_abap_random_packed_dec7=>create( seed = cl_abap_random=>seed( ) min = CONV cl_abap_random_packed_dec7=>p31_7( min_value ) max = CONV cl_abap_random_packed_dec7=>p31_7( max_value ) )->get_next( ).
CREATE DATA packed_number LIKE h.
packed_number->* = h.
WHEN 8.
DATA(i) = cl_abap_random_packed_dec8=>create( seed = cl_abap_random=>seed( ) min = CONV cl_abap_random_packed_dec8=>p31_8( min_value ) max = CONV cl_abap_random_packed_dec8=>p31_8( max_value ) )->get_next( ).
CREATE DATA packed_number LIKE i.
packed_number->* = i.
WHEN 9.
DATA(j) = cl_abap_random_packed_dec9=>create( seed = cl_abap_random=>seed( ) min = CONV cl_abap_random_packed_dec9=>p31_9( min_value ) max = CONV cl_abap_random_packed_dec9=>p31_9( max_value ) )->get_next( ).
CREATE DATA packed_number LIKE j.
packed_number->* = j.
WHEN 10.
DATA(k) = cl_abap_random_packed_dec10=>create( seed = cl_abap_random=>seed( ) min = CONV cl_abap_random_packed_dec10=>p31_10( min_value ) max = CONV cl_abap_random_packed_dec10=>p31_10( max_value ) )->get_next( ).
CREATE DATA packed_number LIKE k.
packed_number->* = k.
WHEN 11.
DATA(l) = cl_abap_random_packed_dec11=>create( seed = cl_abap_random=>seed( ) min = CONV cl_abap_random_packed_dec11=>p31_11( min_value ) max = CONV cl_abap_random_packed_dec11=>p31_11( max_value ) )->get_next( ).
CREATE DATA packed_number LIKE l.
packed_number->* = l.
WHEN 12.
DATA(m) = cl_abap_random_packed_dec12=>create( seed = cl_abap_random=>seed( ) min = CONV cl_abap_random_packed_dec12=>p31_12( min_value ) max = CONV cl_abap_random_packed_dec12=>p31_12( max_value ) )->get_next( ).
CREATE DATA packed_number LIKE m.
packed_number->* = m.
WHEN 13.
DATA(n) = cl_abap_random_packed_dec13=>create( seed = cl_abap_random=>seed( ) min = CONV cl_abap_random_packed_dec13=>p31_13( min_value ) max = CONV cl_abap_random_packed_dec13=>p31_13( max_value ) )->get_next( ).
CREATE DATA packed_number LIKE n.
packed_number->* = n.
WHEN 14.
DATA(o) = cl_abap_random_packed_dec14=>create( seed = cl_abap_random=>seed( ) min = CONV cl_abap_random_packed_dec14=>p31_14( min_value ) max = CONV cl_abap_random_packed_dec14=>p31_14( max_value ) )->get_next( ).
CREATE DATA packed_number LIKE o.
packed_number->* = o.
ENDCASE.
CATCH cx_root.
ENDTRY.
ENDMETHOD.
METHOD get_random_n.
IF length > max_length OR length < 1.
DATA(len) = max_length.
ELSE.
len = length.
ENDIF.
random_n = get_random_number_sequence( len ).
ENDMETHOD.
METHOD get_random_d.
DATA(int) = cl_abap_random_int=>create( seed = cl_abap_random=>seed( )
min = -100
max = 100 )->get_next( ).
random_d = start_date + int.
ENDMETHOD.
METHOD get_random_t.
DATA(int) = cl_abap_random_int=>create( seed = cl_abap_random=>seed( )
min = -36000
max = 36000 )->get_next( ).
random_t = start_time + int.
ENDMETHOD.
METHOD get_random_utclong.
DATA(int) = cl_abap_random_int=>create( seed = cl_abap_random=>seed( )
min = -100
max = 100 )->get_next( ).
random_utc = utclong_add( val = utclong_current( )
days = int
hours = int
minutes = int
seconds = int ).
ENDMETHOD.
METHOD get_random_dec16.
random_dec16 = cl_abap_random_decfloat16=>create( seed = cl_abap_random=>seed( ) )->get_next( ).
ENDMETHOD.
METHOD get_random_dec34.
random_dec34 = cl_abap_random_decfloat34=>create( seed = cl_abap_random=>seed( ) )->get_next( ).
ENDMETHOD.
METHOD get_random_f.
random_f = cl_abap_random_float=>create( seed = cl_abap_random=>seed( ) )->get_next( ).
ENDMETHOD.
METHOD get_random_x.
DATA(random_string) = get_random_string( length ).
random_x = cl_abap_conv_codepage=>create_out( codepage = `UTF-8` )->convert( random_string ).
ENDMETHOD.
METHOD get_random_xstring.
DATA(random_string) = get_random_string( ).
random_xstring = cl_abap_conv_codepage=>create_out( codepage = `UTF-8` )->convert( random_string ).
ENDMETHOD.
METHOD add_table_entries.
IF table_entry_count < 0.
table_entry_count = 1.
ENDIF.
IF table_entry_count > max_table_entry_count.
table_entry_count = max_table_entry_count.
ENDIF.
DO table_entry_count TIMES.
INSERT INITIAL LINE INTO TABLE itab->* ASSIGNING FIELD-SYMBOL( |
Demo ABAP Doc comments
"! "!This class serves as an example to illustrate comments for ABAP Doc.
"! The comments begin with the string "!, a special form of regular comments introduced by ".
"! The {@link zcl_demo_abap.METH:calculate} method of the example class performs a calculation.
This method performs a calculation.
"! @parameter num1 | First number for the calcation "! @parameter num2 | Second number for the calcation "! @parameter operator | Operator. Only one of the four operators +, -, *, / is allowed. "! The value is represented by an enumerated type. Note that there is no handling if "! the assigned value is initial. "! @parameter result | Result of the calculation "! @raising cx_sy_zerodivide | Zero division "! @raising cx_sy_arithmetic_overflow | Arithmetic overflow CLASS-METHODS calculate IMPORTING num1 TYPE i num2 TYPE i operator TYPE t_enum_calc RETURNING VALUE(result) TYPE decfloat34 RAISING cx_sy_zerodivide cx_sy_arithmetic_overflow. "! This is an ABAP Doc comment for a constant CONSTANTS const TYPE i VALUE 123. "! This is an ABAP Doc comment for a static attribute of a class CLASS-DATA dobj TYPE i. PROTECTED SECTION. PRIVATE SECTION. ENDCLASS. CLASS zcl_demo_abap IMPLEMENTATION. METHOD if_oo_adt_classrun~main. DATA(result_plus) = calculate( num1 = 1 num2 = 10 operator = en_calc-plus ). DATA(result_minus) = calculate( num1 = 1 num2 = 10 operator = en_calc-minus ). DATA(result_multiply) = calculate( num1 = 2 num2 = 5 operator = en_calc-multiply ). DATA(result_divide) = calculate( num1 = 10 num2 = 5 operator = en_calc-divide ). out->write( data = result_plus name = `result_plus` ). out->write( data = result_minus name = `result_minus` ). out->write( data = result_multiply name = `result_multiply` ). out->write( data = result_divide name = `result_divide` ). ENDMETHOD. METHOD calculate. result = SWITCH #( operator WHEN en_calc-plus THEN num1 + num2 WHEN en_calc-minus THEN num1 - num2 WHEN en_calc-multiply THEN num1 * num2 WHEN en_calc-divide THEN num1 / num2 ELSE '0' ). ENDMETHOD. ENDCLASS. ``` ### Escaping Characters - You may stumble on [`!` characters](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/ABENNAMES_ESCAPING.html) specified before operands. - They are used to distinguish the operand's name from ABAP words. - When compiling ABAP programs, the specifications with the escape character are not considered as ABAP words. - When executing the programs, the escape characters are ignored. The following nonsensical example shows various specifications with the escape character that emphasize in the program that the operands are not to be confused with ABAP words. These specifications are not mandatory in the example. The example only addresses escape characters you may stumble on in ABAP code. ```abap CLASS zcl_demo_abap DEFINITION PUBLIC FINAL CREATE PUBLIC . PUBLIC SECTION. INTERFACES if_oo_adt_classrun. DATA num TYPE i. CLASS-DATA default TYPE i VALUE 1. METHODS meth1 IMPORTING !num TYPE i. METHODS !methods IMPORTING !raising TYPE i OPTIONAL !optional TYPE i !exporting TYPE i EXPORTING !importing TYPE i !changing TYPE i CHANGING !default TYPE i. PROTECTED SECTION. PRIVATE SECTION. ENDCLASS. CLASS zcl_demo_abap IMPLEMENTATION. METHOD if_oo_adt_classrun~main. meth1( 1 ). DATA !exporting TYPE i. DATA !changing TYPE i. methods( EXPORTING raising = 1 optional = 5 exporting = 10 IMPORTING importing = !exporting changing = !changing CHANGING default = !default ). ENDMETHOD. METHOD meth1. DATA(a) = num. DATA(b) = me->num. DATA(c) = !num. me->num = num. me->num = !num. ENDMETHOD. METHOD methods. !importing = !raising + !optional. !changing = !exporting. !default += 1. importing = raising + optional. changing = exporting. default += 1. ENDMETHOD. ENDCLASS. ``` ## More Information You can check the subtopics of - [ABAP Objects - Overview](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenabap_objects_oview.htm) - [Programming Guidlines - Object-Oriented Programming (F1 docu for standard ABAP)](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abenobj_oriented_gdl.htm) in the ABAP Keyword Documentation. ## Executable Examples - [zcl_demo_abap_objects](./src/zcl_demo_abap_objects.clas.abap) - [zcl_demo_abap_objects_misc](./src/zcl_demo_abap_objects_misc.clas.abap): Additional syntax examples - [zcl_demo_abap_oo_inheritance_1](./src/zcl_demo_abap_oo_inheritance_1.clas.abap): Focuses on inheritance; the inheritance tree consists of 4 example classes > **💡 Note**