This commit is contained in:
danrega
2024-06-13 12:50:12 +02:00
parent b65faccce0
commit c2f31ff896
3 changed files with 203 additions and 27 deletions

View File

@@ -158,13 +158,18 @@ CLASS global_class IMPLEMENTATION.
ENDCLASS.
```
> **💡 Note**<br>
> - Addition `... 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").
> - Addition `... 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.
> - The code snippet above shows the syntax to create a global class (indicated by `PUBLIC`), that is instantiable everywhere (indicated by `CREATE PUBLIC`) but that does not allow inheritance (indicated by `FINAL`, and which is covered further down).
> - There are more additions that can be specified. Find more information on the additions [here](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapclass_options.htm).
> - Examples:
> - `... 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. 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).
> - `... [GLOBAL] 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. The `GLOBAL` addition can be used together with the `PUBLIC` addition and be specified with other global classes/interfaces following `GLOBAL FIRENDS`. Note: For local classes/interfaces, the addition [`LOCAL FRIENDS`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapclass_local_friends.htm) is available.
> - `... 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.`: Making 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).
<p align="right"><a href="#top">⬆️ back to top</a></p>
@@ -301,7 +306,7 @@ ENDCLASS.
CLASS ltc_test IMPLEMENTATION.
METHOD test_calculate.
"Creating an object of class under test
"Creating an object of the class under test
DATA(ref_cut) = NEW zcl_demo_test( ).
"Calling method that is to be tested
@@ -371,7 +376,11 @@ Summary:
#### Creating the Visibility Sections
At least one section must be specified.
``` abap
CLASS local_class DEFINITION.
CLASS zcl_some_class DEFINITION
PUBLIC
FINAL
CREATE PUBLIC.
PUBLIC SECTION.
"Here go the components.
PROTECTED SECTION.
@@ -379,6 +388,8 @@ CLASS local_class DEFINITION.
PRIVATE SECTION.
"Here go the components.
ENDCLASS.
...
```
<p align="right"><a href="#top">⬆️ back to top</a></p>
@@ -436,12 +447,15 @@ can be used in the public visibility section. Effect:
> - Can only be changed using methods of the class or its subclasses
> - Note that when creating attributes in the public visibility section, they are globally visible and can therefore be globally used. Note the consequences on the users when changing attributes in the public visibility section (e.g. making an attribute read-only at a later point in time when, for example, other classes use the attribute).
Declaring attributes in visibility sections. In the code snippet below, all attributes are declared in the public section of a local class.
Declaring attributes in visibility sections. In the code snippet below, all attributes are declared in the public section.
``` abap
CLASS local_class DEFINITION.
CLASS zcl_some_class DEFINITION
PUBLIC
FINAL
CREATE PUBLIC.
PUBLIC SECTION.
TYPES some_type TYPE c LENGTH 3. "Type declaration
TYPES some_type TYPE c LENGTH 3. "Type declaration
DATA: inst_number TYPE i, "Instance attributes
inst_string TYPE string,
@@ -450,7 +464,7 @@ CLASS local_class DEFINITION.
CLASS-DATA: stat_number TYPE i, "Static attributes
stat_char TYPE c LENGTH 3.
CONSTANTS const_num TYPE i VALUE 123. "Non-changeable constant
CONSTANTS const_num TYPE i VALUE 123. "Non-changeable constant
PROTECTED SECTION.
"Here go more attributes if needed.
@@ -460,7 +474,7 @@ CLASS local_class DEFINITION.
ENDCLASS.
CLASS local_class IMPLEMENTATION.
CLASS zcl_some_class IMPLEMENTATION.
... "Here go all method implementations.
@@ -507,6 +521,7 @@ In the simplest form, methods can have no parameter at all. Apart from that, met
> **💡 Note**<br>
> - Find more information [here](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapmethods_general.htm).
> - You may find the addition `EXCEPTIONS` especially in definitions of older classes. They are for non-class-based exceptions. This addition should not be used in ABAP for Cloud Development.
> - Notes on [formal
parameter](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenformal_parameter_glosry.htm "Glossary Entry")
@@ -577,12 +592,16 @@ In the simplest form, methods can have no parameter at all. Apart from that, met
**Example for method definitions**
The following snippet shows
multiple method definitions in the public section of a local class. Most of the formal
multiple method definitions in the public section of a global class. Most of the formal
parameters of the demo methods below are defined by just using the
parameter name. This means passing by reference (returning parameters
require to be passed by value).
``` abap
CLASS local_class DEFINITION.
CLASS zcl_some_class DEFINITION
PUBLIC
FINAL
CREATE PUBLIC.
PUBLIC SECTION.
METHODS: inst_meth1, "instance methods
@@ -628,7 +647,7 @@ CLASS local_class DEFINITION.
ENDCLASS.
CLASS local_class IMPLEMENTATION.
CLASS zcl_some_class IMPLEMENTATION.
METHOD inst_meth1.
...
ENDMETHOD.
@@ -980,7 +999,7 @@ CLASS zcl_demo_test DEFINITION
INTERFACES if_oo_adt_classrun.
"------------------------ Attributes ------------------------
"Instance attribute
"Instance attributes
DATA: inst_attr TYPE utclong,
inst_string TYPE string.
@@ -1169,7 +1188,7 @@ CLASS zcl_demo_test IMPLEMENTATION.
"- See the method implementation of inst_meth1. It shows that
" instance methods can access both static and instance attributes.
"- As mentioned above regarding the attributes, in the same class and
" in this example, you can call the methods directly (without via
" in this example, you can call the methods directly (without using
" a reference variable).
inst_meth1( ).
@@ -1308,7 +1327,7 @@ CLASS zcl_demo_test IMPLEMENTATION.
"The ipow function is included in the method implementation. The
"second example raises the exception.
"No TRY control structure, no syntax warning at compile. However,
"No TRY control structure, no syntax warning at compile time. However,
"the calculation works.
DATA(power_res1) = oref->inst_meth7( ip1 = 5 ip2 = 2 ).
out->write( data = power_res1 name = `power_res1` ).

View File

@@ -6,6 +6,7 @@
- [Introduction](#introduction)
- [VALUE](#value)
- [CORRESPONDING](#corresponding)
- [NEW](#new)
- [CONV](#conv)
- [EXACT](#exact)
- [REF](#ref)
@@ -579,7 +580,9 @@ two statements are not the same:
- This addition allows the assignment of values for a target component based on an expression (which is evaluated before the `CORRESPONDING` expression).
- `DEFAULT` can be preceded by the source component. In this case, the source component's value is assigned to the left-hand side only if the source component is not initial. If it is initial, the value of the expression following the `DEFAULT` addition is assigned.
´´´abap
Examples:
```abap
"Creating and populating data objects to work with
DATA: BEGIN OF struc1,
id1 TYPE i,
@@ -656,8 +659,6 @@ struc2 = CORRESPONDING #(
*1 a hallo 2 d 30
```
<p align="right"><a href="#top">⬆️ back to top</a></p>
## NEW
@@ -1172,6 +1173,8 @@ the style of
statements, i. e. it uses the value of only a single variable that is
checked in the case distinction.
Examples:
``` abap
"The following example performs a calculation (no error handling implemented)
"if a valid operator is passed, and stores the result in a data object of
@@ -1390,7 +1393,7 @@ DATA(f14) = FILTER #( fi_tab2 USING KEY sec_key EXCEPT IN filter_tab2 WHERE a =
- In the definition, the right-hand side value is declared as if an inline declaration is used. The data type is derived accordingly.
- Only to be used in constructor expressions (see the syntax diagrams in the ABAP Keyword Documentation where exactly [`LET`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abaplet.htm) expressions can be specified).
See the following simple examples to get an idea about the use:
See the following examples to get an idea about the use:
```abap
"Data type and object to work with in the example
@@ -1530,6 +1533,8 @@ ENDDO.
- In contrast to `LOOP` statements, the sequential processing
cannot be debugged.
Examples:
```abap
"Data objects and types to work with in the examples
TYPES: BEGIN OF s,
@@ -1894,6 +1899,8 @@ DATA(abap_str) = REDUCE string( INIT text = ``
Find more information in the [Internal Tables: Grouping](11_Internal_Tables_Grouping.md) cheat sheet.
Examples:
```abap
"Data objects and types to work with in the examples
TYPES: BEGIN OF s,

View File

@@ -29,6 +29,7 @@
- [Validating Input for Dynamic Specifications (CL\_ABAP\_DYN\_PRG)](#validating-input-for-dynamic-specifications-cl_abap_dyn_prg)
- [Runtime Type Services (RTTS)](#runtime-type-services-rtts)
- [Getting Type Information at Runtime](#getting-type-information-at-runtime)
- [Example: Exploring the RTTI Type Hierarchy](#example-exploring-the-rtti-type-hierarchy)
- [Excursion: Inline Declaration, CAST Operator, Method Chaining](#excursion-inline-declaration-cast-operator-method-chaining)
- [Absolute Names](#absolute-names)
- [Dynamically Creating Data Types at Runtime](#dynamically-creating-data-types-at-runtime)
@@ -1867,6 +1868,152 @@ CALL METHOD oref2->('TRIPLE') PARAMETER-TABLE ptab.
result = ptab[ name = 'R_TRIPLE' ]-('VALUE')->*. "9
```
**Example Class**
The commented example class below explores dynamic method calls with a simple method. You can create a demo class called `zcl_some_class` and copy and paste the following code. Once activated, you can choose *F9* in ADT to run the class. The example is designed to display output in the console that shows the result of calling different methods.
```abap
CLASS zcl_some_class DEFINITION
PUBLIC
FINAL
CREATE PUBLIC .
PUBLIC SECTION.
INTERFACES if_oo_adt_classrun.
METHODS meth IMPORTING num1 TYPE i
num2 TYPE i
EXPORTING add TYPE i
subtr TYPE i
CHANGING abs_val TYPE i
RETURNING VALUE(ret) TYPE string.
PROTECTED SECTION.
PRIVATE SECTION.
ENDCLASS.
CLASS zcl_some_class IMPLEMENTATION.
METHOD if_oo_adt_classrun~main.
"-------------------- Static method call --------------------
"Creating object reference
DATA(oref_stat) = NEW zcl_some_class( ).
DATA: calc_result_addition TYPE i,
calc_result_subtraction TYPE i,
some_number TYPE i VALUE -123.
DATA(result_stat) = oref_stat->meth( EXPORTING num1 = 7
num2 = 3
IMPORTING add = calc_result_addition
subtr = calc_result_subtraction
CHANGING abs_val = some_number ).
out->write( data = calc_result_addition name = `calc_result_addition` ).
out->write( data = calc_result_subtraction name = `calc_result_subtraction` ).
out->write( data = some_number name = `some_number` ).
out->write( data = result_stat name = `result_stat` ).
out->write( repeat( val = `*` occ = 80 ) ).
"-------------------- Dynamic method calls --------------------
"The following method calls explore possible dynamic equivalents
"of the previous static method call.
"Creating an instance of a class by specifying the type dynamically
DATA oref TYPE REF TO object.
CREATE OBJECT oref TYPE ('ZCL_SOME_CLASS').
some_number = -99.
"Specifying parameters statically
DATA result_dyn TYPE string.
CALL METHOD oref->('METH')
EXPORTING
num1 = 10
num2 = 4
IMPORTING
add = calc_result_addition
subtr = calc_result_subtraction
CHANGING
abs_val = some_number
RECEIVING
ret = result_dyn.
out->write( data = calc_result_addition name = `calc_result_addition` ).
out->write( data = calc_result_subtraction name = `calc_result_subtraction` ).
out->write( data = some_number name = `some_number` ).
out->write( data = result_dyn name = `result_dyn` ).
out->write( repeat( val = `*` occ = 80 ) ).
"The following examples show erroneous dynamic method calls
"Missing parameters
TRY.
CALL METHOD oref->('METH').
CATCH cx_root INTO DATA(error).
DATA(cx_class) = cl_abap_typedescr=>describe_by_object_ref( error )->get_relative_name( ).
out->write( |{ cx_class } raised: { error->get_text( ) }| ).
out->write( repeat( val = `*` occ = 80 ) ).
ENDTRY.
"Illegal type of an actual parameter
TRY.
CALL METHOD oref->('METH')
EXPORTING
num1 = 'nope'
num2 = 1
IMPORTING
add = calc_result_addition
subtr = calc_result_subtraction
CHANGING
abs_val = some_number
RECEIVING
ret = result_dyn.
CATCH cx_root INTO error.
cx_class = cl_abap_typedescr=>describe_by_object_ref( error )->get_relative_name( ).
out->write( |{ cx_class } raised: { error->get_text( ) }| ).
out->write( repeat( val = `*` occ = 80 ) ).
ENDTRY.
"Dynamic method call using a parameter table
DATA(ptab) = VALUE abap_parmbind_tab( ( name = 'NUM1'
kind = cl_abap_objectdescr=>exporting
value = NEW i( 2 ) )
( name = 'NUM2'
kind = cl_abap_objectdescr=>exporting
value = NEW i( 10 ) )
( name = 'ADD'
kind = cl_abap_objectdescr=>importing
value = NEW i( ) )
( name = 'SUBTR'
kind = cl_abap_objectdescr=>importing
value = NEW i( ) )
( name = 'ABS_VAL'
kind = cl_abap_objectdescr=>changing
value = NEW i( -987 ) )
( name = 'RET'
kind = cl_abap_objectdescr=>returning
value = NEW string( ) ) ).
CALL METHOD oref->('METH') PARAMETER-TABLE ptab.
out->write( ptab ).
ENDMETHOD.
METHOD meth.
add = num1 + num2.
subtr = num1 - num2.
DATA(abs_val_copy) = abs_val.
"Getting the absolute value
abs_val = abs( abs_val ).
ret = |Values of importing parameters: num1 = { num1 STYLE = SIMPLE }| &&
|, num2 = { num2 STYLE = SIMPLE }\nValues of exporting parameters: | &&
|add = { add STYLE = SIMPLE }, subtr = { subtr STYLE = SIMPLE }| &&
|\nChanging parameter: abs_val (original) = { abs_val_copy STYLE = SIMPLE }, | &&
|abs_val (modified) = { abs_val STYLE = SIMPLE }|.
ENDMETHOD.
ENDCLASS.
```
**Excursion**
The following simplified example highlights several things in the context of a dynamic invoke example:
@@ -2102,6 +2249,8 @@ The type properties are represented by attributes that are accessible through th
> - For each type category (elementary type, table, and so on), there is a type description class (e.g. `CL_ABAP_STRUCTDESCR` for structures, as shown in the hierarchy tree above) that has special attributes (i.e. the properties of the respective types).
> - References to type description objects can be used, for example, after the `TYPE HANDLE` addition of the `CREATE DATA` and `ASSIGN` statements.
#### Example: Exploring the RTTI Type Hierarchy
The following example explores the RTTI type hierarchy and demonstrates how to retrieve various pieces of type information using RTTI attributes and methods. You can create a demo class (adapt the class name if needed), copy and paste the code, run the class with F9 in ADT, and check the output in the console.
The example includes demo objects that are added to an internal table. This table is then looped over to retrieve type information for all objects. To retrieve a type description object, you have multiple options. You can use the static methods of the `cl_abap_typedescr` class, which is the root class of the RTTI hierarchy. These methods include:
@@ -2385,12 +2534,13 @@ CLASS zcl_some_class IMPLEMENTATION.
DATA(applies_dref4) = data_ref->applies_to_data_ref( NEW ref_str( ) ).
INSERT |{ tabix } Applies: 1) "{ applies_dref1 }" 2) "{ applies_dref2 }"| &&
| / 3) "{ applies_dref3 }" 4) "{ applies_dref4 }"| INTO TABLE str_tab.
| 3) "{ applies_dref3 }" 4) "{ applies_dref4 }"| INTO TABLE str_tab.
"Dynamically creating data objects based on the ...
TRY.
"... absolute name
CREATE DATA dyn_dobj TYPE (absolute_name).
"... absolute name of the referenced data object
DATA(absolute_name_ref) = dref_referenced_type->absolute_name.
CREATE DATA dyn_dobj TYPE REF TO (absolute_name_ref).
"Assigning the value to the dynamically created data object
dyn_dobj->* = type->*.