forked from SAP-samples/abap-cheat-sheets
-
Notifications
You must be signed in to change notification settings - Fork 0
/
zcl_demo_abap_constructor_expr.clas.abap
1456 lines (1090 loc) · 54.7 KB
/
zcl_demo_abap_constructor_expr.clas.abap
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
***********************************************************************
*
* ABAP cheat sheet: Constructor expressions
*
* -------------------------- PURPOSE ----------------------------------
* - Example to demonstrate the use of constructor expressions.
* - Topics covered: Operators VALUE, CORRESPONDING, NEW, CONV, EXACT, REF,
* CAST, COND, SWITCH, FILTER, REDUCE, iteration expressions with FOR,
* LET expressions
*
* ----------------------- GETTING STARTED -----------------------------
* - Open the class with the ABAP development tools for Eclipse (ADT).
* - Choose F9 to run the class.
* - Check the console output.
* - To understand the context and the ABAP syntax used, refer to the
* notes included in the class as comments or refer to the respective
* topic in the ABAP Keyword Documentation.
* - Due to the amount of console output, the examples contain numbers
* (e.g. 1) ..., 2) ..., 3) ...) for the individual example sections.
* Also, the variable name is displayed in most cases. So to find
* the relevant output in the console easier and faster, just search
* for the number/variable name in the console (CTRL+F in the console)
* or use the debugger.
*
* ----------------------------- NOTE -----------------------------------
* The code presented in this class is intended only to support the ABAP
* cheat sheets. It is not intended for direct use in a production system
* environment. The code examples in the ABAP cheat sheets are primarily
* intended to provide a better explanation and visualization of the
* syntax and semantics of ABAP statements, not to solve concrete
* programming tasks. For production application programs, you should
* always work out your own solution for each individual case. There is
* no guarantee for the correctness or completeness of the code.
* Furthermore, there is no legal responsibility or liability for any
* errors or their consequences that may occur when using the the example
* code.
*
***********************************************************************
"! <p class="shorttext synchronized">ABAP cheat sheet: Constructor expressions</p>
"! Example to demonstrate the use of constructor expressions.<br>Choose F9 in ADT to run the class.
CLASS zcl_demo_abap_constructor_expr DEFINITION
PUBLIC
FINAL
CREATE PUBLIC .
PUBLIC SECTION.
INTERFACES: if_oo_adt_classrun.
protected section.
PRIVATE SECTION.
TYPES: BEGIN OF line1,
col1 TYPE i,
col2 TYPE i,
END OF line1,
BEGIN OF line2,
col2 TYPE i,
col3 TYPE i,
col4 TYPE i,
END OF line2,
BEGIN OF s1_type,
comp1 TYPE c LENGTH 1,
comp2 TYPE string,
comp3 TYPE i,
END OF s1_type,
BEGIN OF s2_type,
comp1 TYPE string,
comp2 TYPE c LENGTH 1,
comp3 TYPE i,
comp4 TYPE i,
END OF s2_type.
CLASS-DATA:
"Deep structures as examples to demonstrate the CORRESPONDING operator
BEGIN OF struc1,
comp1 TYPE c LENGTH 1 VALUE 'W',
BEGIN OF struc_nested,
comp1 TYPE c LENGTH 1 VALUE 'X',
BEGIN OF comp2,
col1 TYPE c LENGTH 1 VALUE 'Y',
col2 TYPE c LENGTH 1 VALUE 'Z',
END OF comp2,
END OF struc_nested,
itab TYPE TABLE OF line1 WITH EMPTY KEY,
END OF struc1,
BEGIN OF struc2,
BEGIN OF struc_nested,
comp1 TYPE string,
comp2 TYPE string,
comp3 TYPE string,
END OF struc_nested,
itab TYPE TABLE OF line2 WITH EMPTY KEY,
comp4 TYPE i,
END OF struc2,
s1 TYPE s1_type,
s2 TYPE s2_type,
tab1 TYPE TABLE OF s1_type WITH EMPTY KEY,
tab2 TYPE TABLE OF s2_type WITH EMPTY KEY,
tab3 TYPE TABLE OF s2_type WITH EMPTY KEY,
tab4 TYPE SORTED TABLE OF s2_type WITH NON-UNIQUE KEY comp3,
nl TYPE string..
CLASS-METHODS:
fill_deep_structures,
fill_struc_and_tab.
ENDCLASS.
CLASS zcl_demo_abap_constructor_expr IMPLEMENTATION.
METHOD fill_deep_structures.
"Clearing all contents of struc2
CLEAR struc2.
"Filling nested tables in deep structures
struc2-struc_nested = VALUE #( comp1 = `aaa`
comp2 = `bbb`
comp3 = `ccc` ).
struc1-itab = VALUE #(
( col1 = 111 col2 = 222 )
( col1 = 333 col2 = 444
) ).
struc2-itab = VALUE #(
( col2 = 1 col3 = 2 col4 = 3 )
( col2 = 4 col3 = 5 col4 = 6 )
( col2 = 7 col3 = 8 col4 = 9 )
).
"Filling individual component that is not shared by both structures
struc2-comp4 = 999.
ENDMETHOD.
METHOD fill_struc_and_tab.
CLEAR: s1, s2, tab1, tab2, tab3.
s1 = VALUE #( comp1 = 'A' comp2 = `bbb` comp3 = 1 ).
s2 = VALUE #( comp1 = `ccc` comp2 = 'D' comp3 = 2 comp4 = 3 ).
tab1 = VALUE #(
( comp1 = 'A' comp2 = `bbb` comp3 = 1 )
( comp1 = 'B' comp2 = `ccc` comp3 = 2 )
( comp1 = 'C' comp2 = `ddd` comp3 = 3 ) ).
tab2 = VALUE #(
( comp1 = `eee` comp2 = 'F' comp3 = 4 comp4 = 5 )
( comp1 = `ggg` comp2 = 'H' comp3 = 6 comp4 = 7 )
( comp1 = `iii` comp2 = 'J' comp3 = 8 comp4 = 9 ) ).
tab3 = VALUE #(
( comp1 = `aaa` comp2 = 'B' comp3 = 1 comp4 = 2 )
( comp1 = `ccc` comp2 = 'D' comp3 = 3 comp4 = 4 )
( comp1 = `eee` comp2 = 'F' comp3 = 5 comp4 = 6 )
( comp1 = `ggg` comp2 = 'H' comp3 = 7 comp4 = 8 )
( comp1 = `iii` comp2 = 'J' comp3 = 9 comp4 = 10 ) ).
tab4 = tab3.
ENDMETHOD.
METHOD if_oo_adt_classrun~main.
DATA(output) = NEW zcl_demo_abap_display( out ).
output->display( `ABAP Cheat Sheet Example: Constructor expressions` ).
output->display( `VALUE` ).
output->display( `1) Structures: Populating a flat structure` ).
"A flat structure is created based on a data type defined with a
"TYPES statement. The structure is then filled using a constructor
"expression with VALUE by specifying the components and assigning
"values. Here, the type can be inferred, hence, a # character can be used.
TYPES: BEGIN OF struc_type,
num TYPE i,
char1 TYPE c LENGTH 3,
char2 TYPE c LENGTH 3,
END OF struc_type.
DATA struc TYPE struc_type.
"Filling structure
struc = VALUE #( num = 1 char1 = 'aaa' char2 = 'abc' ).
output->display( input = struc name = `struc` ).
**********************************************************************
output->next_section( `2) Structures: Omitting value assignment to components / BASE addition` ).
"The same structure is then filled purposely omitting components, i.
"e. these components remain initial.
struc = VALUE #( char1 = 'bbb' ).
output->display( input = struc name = `struc` ).
"You can use the BASE addition to retain existing content
"Compare with the BASE example further down regarding internal tables: There are
"no extra parentheses within the outer pair of parentheses.
struc = VALUE #( BASE struc char2 = 'xyz' ).
output->display( input = struc name = `struc` ).
**********************************************************************
output->next_section( `3) Structures: Inline declaration, explicit type specification` ).
"The example demonstrates a variable that is declared inline. Here,
"the result is a structure which is filled using a constructor
"expression with VALUE and by specifying the components and assigning
"values in parentheses. The structure type is specified explicitly.
"The # symbol would not work since no type can be inferred from the
"specified parameters.
DATA(struc_inl) = VALUE struc_type( num = 3
char1 = 'ccc'
char2 = 'def' ).
output->display( input = struc_inl name = `struc_inl` ).
**********************************************************************
output->next_section( `4) Internal tables: Declaration and population` ).
"The example demonstrates the declaration of an internal table. The
"internal table is then filled using a constructor expression with
"VALUE.
"The type can be inferred here and need not be specified explicitly.
"Note the extra pair of parentheses in which the components are
"specified and assigned values. In the example, 3 lines are added to
"the table. For one line, some components are purposely not assigned.
DATA itab TYPE TABLE OF struc_type WITH EMPTY KEY.
itab = VALUE #( ( num = 1 char1 = 'aaa' char2 = 'abc' )
( num = 2 char1 = 'bbb' char2 = 'def' )
( num = 3 char1 = 'ccc' ) ).
output->display( input = itab name = `itab` ).
**********************************************************************
output->next_section( `5) Internal tables: Inline declaration, explicit type specification` ).
"The example demonstrates an internal table declared inline that is
"filled using a constructor expression with VALUE by specifying the
"internal table type explicitly. Note that the internal table type
"cannot be generic in this context.
TYPES: itab_type TYPE STANDARD TABLE OF struc_type
WITH NON-UNIQUE KEY num.
DATA(itab2) = VALUE itab_type(
( num = 4 char1 = 'ddd' char2 = 'ghi' )
( num = 5 char1 = 'eee' char2 = 'jkl' ) ).
DATA(str_table) = VALUE string_table( ( `this` )
( `is a` )
( `table` )
( `of type string` ) ).
output->display( input = itab2 name = `itab2` ).
output->display( input = str_table name = `str_table` ).
**********************************************************************
output->next_section( `6) LINES OF addition` ).
"Using the LINES OF addition, you can add lines of other tables.
"Note: The line type of the other internal table must match the one of
"the target internal table. Using FROM/TO, the table line selection can
"be further restricted. Without FROM/TO, all lines of the table are
"respected.
itab2 = VALUE #( ( num = 6 char1 = 'fff' char2 = 'mno' )
( LINES OF itab )
( LINES OF itab FROM 1 TO 2 ) ).
output->display( input = itab2 name = `itab2` ).
**********************************************************************
output->next_section( `7) BASE addition for keeping existing data` ).
"Using the BASE addition, you can keep existing content of the source
"internal table.
itab2 = VALUE #( BASE itab2 ( num = 7 char1 = 'ggg' char2 = 'pqr' ) ).
output->display( input = itab2 name = `itab2` ).
**********************************************************************
output->next_section( `8) Assignemnt with the VALUE operator without specifying content in parentheses` ).
"Using the VALUE operator without populating anything in the parentheses,
"data objects are initialized.
"elementary types
DATA(some_num) = 123.
some_num = VALUE #( ).
DATA(another_num) = VALUE i( ).
DATA(some_str) = `hallo`.
some_str = VALUE #( ).
"Initializing internal table/structure
str_table = VALUE #( ).
struc = VALUE #( ).
output->display( input = some_num name = `some_num` ).
output->display( input = another_num name = `another_num` ).
output->display( input = some_str name = `some_str` ).
output->display( input = str_table name = `str_table` ).
output->display( input = struc name = `struc` ).
**********************************************************************
output->next_section( `Excursions: VALUE operator in use with ABAP statements and ABAP SQL statements` ).
"The following examples use ABAP and ABAP SQL statements in which table lines
"are constructed inline using the VALUE operator.
output->display( `9) Modifying internal table from a structure created inline` ).
MODIFY TABLE itab2 FROM VALUE #( num = 7 char1 = 'hhh' char2 = 'stu' ).
output->display( input = itab2 name = `itab2` ).
**********************************************************************
output->next_section( `10) Inserting a table line that is created inline into an internal table` ).
INSERT VALUE #( num = 8 char1 = 'iii' char2 = 'vwx' ) INTO TABLE itab2.
output->display( input = itab2 name = `itab2` ).
**********************************************************************
output->next_section( `11) Deleting a table entry based on a line created inline` ).
DELETE TABLE itab2 FROM VALUE #( num = 3 ).
output->display( input = itab2 name = `itab2` ).
**********************************************************************
output->next_section( `12) Modifying a database table based on an internal table created inline` ).
"Deleting demo database table entries for the following example
DELETE FROM zdemo_abap_carr.
MODIFY zdemo_abap_carr FROM TABLE @( VALUE #(
( carrid = 'CO'
carrname = 'Continental Airlines'
currcode = 'USD'
url = 'http://www.continental.com' )
( carrid = 'SQ'
carrname = 'Singapore Airlines'
currcode = 'SGD'
url = 'http://www.singaporeair.com' )
) ).
"Retrieving table entries for display purposes
SELECT FROM zdemo_abap_carr
FIELDS carrid, carrname, currcode, url
ORDER BY carrid
INTO TABLE @DATA(itab_carr).
output->display( input = itab_carr name = `itab_carr` ).
**********************************************************************
output->next_section( `Excursion: Deep structures and tables` ).
output->display( `13) Deep structure` ).
"The example demonstrates the use of constructor expressions with
"VALUE in the context of a deep structure. Here, a structure is declared
"inline and filled. The structure type includes a nested structure. The
"nested structure is filled using a nested VALUE expression.
TYPES: BEGIN OF deep_struc_ty,
num TYPE i,
char1 TYPE c LENGTH 3,
BEGIN OF substruc,
int TYPE i,
str TYPE string,
END OF substruc,
END OF deep_struc_ty.
DATA(deep_struc) = VALUE deep_struc_ty( num = 1
char1 = 'aaa'
substruc = VALUE #( int = 123 str = `hallo` ) ).
output->display( input = deep_struc name = `deep_struc` ).
**********************************************************************
output->next_section( `14) Deep internal table` ).
"A deep internal table is created. Also here, nested VALUE
"expressions are demonstrated.
TYPES: BEGIN OF deep_struc_ty2,
char TYPE c LENGTH 3,
tab TYPE TABLE OF i WITH EMPTY KEY,
END OF deep_struc_ty2.
TYPES: itab_deep_type TYPE STANDARD TABLE OF deep_struc_ty2
WITH NON-UNIQUE KEY char.
DATA(deep_itab) = VALUE itab_deep_type(
( char = 'aaa' tab = VALUE #( ( 1 ) ( 2 ) ( 3 ) ) )
( char = 'bbb' tab = VALUE #( ( 4 ) ( 5 ) ( 6 ) ) ) ).
output->display( input = deep_itab name = `deep_itab` ).
**********************************************************************
output->next_section( `CORRESPONDING` ).
output->display( `Simple Examples with structures and internal tables` ).
"Method to fill demo structures and internal tables
"with values to work with
fill_struc_and_tab( ).
output->display( `15) Original structure and table content` ).
"Displaying the original structures and tables that are filled in the
"course of a method call. The structures and tables are filled anew
"throughout the examples so that all CORRESPONDING expressions are based
"on the same values.
output->display( input = s1 name = `s1` ).
output->display( input = s2 name = `s2` ).
output->display( input = tab1 name = `tab1` ).
output->display( input = tab2 name = `it_st` ).
**********************************************************************
output->next_section( `16) CORRESPONDING without addition` ).
"The target structure and table have a different type but identically
"named components. The identically named components are filled. Note
"that the target variables are initialized here. Also note the effect
"of an automatic conversion of a variable-length string to a
"fixed-length string (one component is typed with c, the other,
"identically named component, is of type string).
s2 = CORRESPONDING #( s1 ).
tab2 = CORRESPONDING #( tab1 ).
output->display( input = s2 name = `s2` ).
output->display( input = tab2 name = `tab2` ).
**********************************************************************
output->next_section( `17) BASE addition for keeping original content` ).
"The BASE addition keeps the original content. Structure: The non-
"identical component name retains its value. Internal table: Existing
"table lines are kept.
fill_struc_and_tab( ).
s2 = CORRESPONDING #( BASE ( s2 ) s1 ).
tab2 = CORRESPONDING #( BASE ( tab2 ) tab1 ).
output->display( input = s2 name = `s2` ).
output->display( input = tab2 name = `tab2` ).
**********************************************************************
output->next_section( `18) MAPPING/EXCEPT additions` ).
"The example demonstrates the additions MAPPING and EXCEPT. MAPPING:
"One component of the target structure is assigned the value of a
"dedicated component of the source structure. EXCEPT: All corresponding
"components are assigned except a specific one.
fill_struc_and_tab( ).
s2 = CORRESPONDING #( s1 MAPPING comp4 = comp3 ).
tab2 = CORRESPONDING #( tab1 EXCEPT comp1 ).
output->display( input = s2 name = `s2` ).
output->display( input = tab2 name = `tab2` ).
**********************************************************************
output->next_section( `CORRESPONDING: Demonstrating various` &&
` additions using deep structures` ).
output->display( `19) Original content of deep structures` ).
"Displaying the original deep structures and tables that are filled in
"the course of a method call. The deep structures and tables are filled
"anew throughout the examples so that all CORRESPONDING expressions are
"based on the same values.
"Method to fill demo deep structures and internal tables
"with values to work with
fill_deep_structures( ).
output->display( input = struc1 name = `struc1` ).
output->display( input = struc2 name = `struc2` ).
**********************************************************************
output->next_section( `20) CORRESPONDING without addition` ).
"CORRESPONDING operator without addition
"Existing contents of identically named components are replaced.
"Existing contents of components in the target structure that are not
"available in the source structure are initialized.
"Contents of the nested structure struc_nested is converted to
"string. Note that the two components of the nested structure in
"component struc_nested-comp2 of struc1 are drawn together when being
"converted to string.
"Contents of struc2-itab are replaced by table contents of struc1-
"itab. Note the value assignment, for example, for col2 in struc2-itab.
"Despite the fact that there is no identically named component comp1 in
"the target structure, values are assigned starting with the first
"column of the source structure. Check the conversion rules for
"internal tables.
struc2 = CORRESPONDING #( struc1 ).
output->display( input = struc2 name = `struc2` ).
**********************************************************************
output->next_section( `21) DEEP addition` ).
"CORRESPONDING operator with the addition DEEP
"Existing contents of identically named components are replaced.
"Existing contents of components in the target structure that are not
"available in the source structure are initialized.
"Contents of the nested structure struc_nested is converted to
"string. Note that the two components of the nested structure in
"component struc_nested-comp2 of struc1 are drawn together when being
"converted to string.
"Contents of struc2-itab are replaced by table contents of struc1-
"itab. Due to the addition DEEP, the value assignment happens for
"identically named components in the nested table. Hence, only col2 as
"the only shared and identically named component is filled.
fill_deep_structures( ).
struc2 = CORRESPONDING #( DEEP struc1 ).
output->display( input = struc2 name = `struc2` ).
**********************************************************************
output->next_section( `22) BASE addition` ).
"CORRESPONDING operator with the addition BASE
"Existing contents of identically named components are replaced.
"Existing contents of components in the target structure that are not
"available in the source structure are kept.
"Contents of the nested structure struc_nested is converted to
"string. Note that the two components of the nested structure in
"component struc_nested-comp2 of struc1 are drawn together when being
"converted to string.
"Contents of struc2-itab are replaced by table contents of struc1-
"itab. The value assignment in the nested table happens like using the
"CORRESPONDING operator without addition. Note the value assignment, for
"example, for col2 in struc2-itab. Despite the fact that there is no
"identically named component col1 in the target structure, values are
"assigned starting with the first column of the source structure. Check
"the conversion rules for internal tables.
fill_deep_structures( ).
struc2 = CORRESPONDING #( BASE ( struc2 ) struc1 ).
output->display( input = struc2 name = `struc2` ).
**********************************************************************
output->next_section( `23) DEEP BASE addition` ).
"CORRESPONDING operator with the additions DEEP BASE
"Existing contents of identically named components are replaced.
"Existing contents of components in the target structure that are not
"available in the source structure are kept.
"Contents of the nested structure struc_nested is converted to
"string. Note that the two components of the nested structure in
"component struc_nested-comp2 of struc1 are drawn together when being
"converted to string.
"Contents of struc2-itab are replaced by table contents of struc1-
"itab. The value assignment in the nested table happens like using the
"CORRESPONDING operator with the addition DEEP. That is, the value
"assignment happens for identically named components in the nested table.
"Hence, only col2 as the only shared and identically named component is filled.
fill_deep_structures( ).
struc2 = CORRESPONDING #( DEEP BASE ( struc2 ) struc1 ).
output->display( input = struc2 name = `struc2` ).
**********************************************************************
output->next_section( `24) APPENDING addition` ).
"CORRESPONDING operator with the addition APPENDING
"Existing contents of identically named components are replaced.
"Existing contents of components in the target structure that are not
"available in the source structure are kept.
"Contents of the nested structure struc_nested is converted to
"string. Note that the two components of the nested structure in
"component struc_nested-comp2 of struc1 are drawn together when being
"converted to string.
"Contents of struc2-itab are kept and contents of struc1-itab are
"added. The value assignment concerning the added lines happens like
"using the CORRESPONDING operator without addition. Note the value
"assignment, for example, for col2 in struc2-itab. Despite the fact that
"there is no identically named component col1 in the target structure,
"values are assigned starting with the first column of the source
"structure. Check the conversion rules for internal tables.
fill_deep_structures( ).
struc2 = CORRESPONDING #( APPENDING ( struc2 ) struc1 ).
output->display( input = struc2 name = `struc2` ).
**********************************************************************
output->next_section( `25) DEEP APPENDING` ).
"CORRESPONDING operator with the additions DEEP APPENDING
"Existing contents of identically named components are replaced.
"Existing contents of components in the target structure that are not
"available in the source structure are kept.
"Contents of the nested structure struc_nested is converted to
"string. Note that the two components of the nested structure in
"component struc_nested-comp2 of struc1 are drawn together when being
"converted to string.
"Contents of struc2-itab are kept and contents of struc1-itab are
"added. The value assignment concerning the added lines happens like
"using the CORRESPONDING operator with the addition DEEP. That is, the
"value assignment happens for identically named components in the nested
"table. Hence, only col2 as the only shared and identically named
"component is filled.
fill_deep_structures( ).
struc2 = CORRESPONDING #( DEEP APPENDING ( struc2 ) struc1 ).
output->display( input = struc2 name = `struc2` ).
**********************************************************************
output->next_section( `NEW` ).
output->display( `26) Creating Anonymous Data Objects` ).
"The examples show the creation of anonymous data objects.
"First, data reference variables are declared using a DATA statement.
"Here, one variable is declared with a complete type, the other one with
"a generic type.
"Then, anonymous data objects are created using the NEW operator. For
"one example, the type can be inferred. In the other example, the type
"is specified explicitly.
"The next examples show the direct assigning of values.
"Furthermore, inline declarations can be used to avoid the prior
"declaration of a variable.
"Declaring data reference variables
DATA dref1 TYPE REF TO i. "Complete type
DATA dref2 TYPE REF TO data. "Generic type
"Creating anonymous data objects
"Here, no parameters are specified within the parentheses meaning the
"data objects retain their initial values.
dref1 = NEW #( ).
dref2 = NEW string( ).
IF dref1->* = 0 AND dref2->* = ``.
DATA(val) = `Initial values`.
ELSE.
val = `No initial values`.
ENDIF.
"Directly assigning values within the parentheses.
dref1 = NEW #( 123 ).
dref2 = NEW string( `hallo` ).
"Inline declaration, explicit type specification
DATA(dref3) = NEW i( 456 ).
"Another constructor expression specified within the parentheses
DATA tx TYPE string VALUE `world`.
DATA(dref4) = NEW string( `Hello ` && tx && CONV string( '!' ) ).
DATA dref5 TYPE REF TO string_table.
dref5 = NEW #( VALUE string_table( ( `a` ) ( `b` ) ) ).
"Structured type; named arguments within the parentheses
DATA(dref6) = NEW zdemo_abap_carr( carrid = 'AA'
carrname = 'American Airlines' ).
output->display( input = val name = `val` ).
output->display( input = dref1 name = `dref1` ).
output->display( input = dref2 name = `dref2` ).
output->display( input = dref3 name = `dref3` ).
output->display( input = dref4 name = `dref4` ).
output->display( input = dref5 name = `dref5` ).
output->display( input = dref6 name = `dref6` ).
**********************************************************************
output->next_section( `27) Creating Instances of Classes` ).
"The example demonstrates the creation of instances of classes.
"First, an object reference variable is declared with a DATA statement.
"As a next step, an instance of a class is created. The type can be
"inferred here. The class has a constructor method defined. Hence, the
"parentheses contain the parameter binding for the constructor method.
"Here, it is only one parameter. That means the explicit specification
"of the parameter name is not needed and the value can be specified
"directly: oref1 = NEW #( `Hallo` ).
"The next examples show object reference variables that are declared
"inline. Here, the type (i. e. the class name) must be specified
"explicitly.
"The last example shows the method chaining that is possible with
"expressions using the NEW operator. The demo class has a method that
"has a returning parameter. In this case, the parameter of the method
"is of type REF TO i.
"Creating an object reference variable
DATA oref1 TYPE REF TO local_class.
"Creating an instance of a class;
"providing parameter bindings for the constructor method
"in the parentheses
oref1 = NEW #( txt = `Hallo` ).
output->display( input = oref1 name = `oref1` ).
"Creating an instance of a class, object reference variable
"is declared inline, explicit type specification
DATA(oref2) = NEW local_class( `Salut` ).
output->display( input = oref2 name = `oref2` ).
"Method chaining
DATA(result) = NEW local_class( `Ciao` )->double( int = NEW #( 5 ) ).
output->display( input = result name = `result` ).
**********************************************************************
output->next_section( `28) CONV` ).
"The examples show the effect of the CONV operator.
"A variable of type i is declared and assigned a value. Then,
"calculations are carried out. The result is stored in a variable
"declared inline. The first result is 0 because the derived type is i.
"The second calculation returns the precise value resulting from the
"division because the CONV
"expression triggers the conversion of the result (decfloat34).
"The next examples demonstrate logical expressions using character-like
"data types.
"A variable is of type abap_bool, i. e. a single character is expected.
"In this case, the variable is initial, i. e. the content is a blank.
"Another variable is of type string. A blank is assigned to this
"variable.
"A logical expression compares the two variables. Without the conversion
"using the CONV operator, the two are not equal due to the comparison
"rules for character-like data types (trailing blanks are not respected
"in variable-length strings). When the string is converted, the
"comparison results to true.
"Declaring data object and assign value
DATA num TYPE i VALUE 1.
"Effect of a calculation ...
"... without conversion
DATA(i) = num / 4.
"... with conversion using an appropriate type
DATA(dec_num) = CONV decfloat34( num / 4 ).
output->display( input = i name = `i` ).
output->display( input = dec_num name = `dec_num` ).
"Declaring data objects
DATA(txt) = VALUE abap_bool( ).
DATA(str) = ` `.
"Comparing the data objects with and without conversion
output->display( `Without conversion:` ).
IF txt = str.
output->display( `txt is equal to str.` ).
ELSE.
output->display( `txt is not equal to str.` ).
ENDIF.
output->display( `With conversion:` ).
IF txt = CONV abap_bool( str ).
output->display( `txt is equal to converted str.` ).
ELSE.
output->display( `txt is not equal to converted str.` ).
ENDIF.
**********************************************************************
output->next_section( `29) EXACT` ).
"The examples show the effect of the EXACT operator that enforces either
"a lossless assignment or a lossless calculation.
"1) Demonstrates data loss when converting to a data object that expects
"only a single character.
"2) Demonstrates an impossible lossless calculation. A rounding is
"necessary in this case.
"3) The example compares the effect of the EXACT and CONV operator.
"Example 1
TRY.
DATA(ex1) = EXACT abap_bool( 'XY' ).
CATCH cx_sy_conversion_data_loss INTO DATA(e1).
DATA(ex2) = e1->value.
DATA(t1) = e1->get_text( ).
ENDTRY.
"Example 2
TRY.
DATA(ex3) = EXACT decfloat34( 1 / 3 ).
CATCH cx_sy_conversion_rounding INTO DATA(e2).
DATA(ex4) = e2->value.
DATA(t2) = e2->get_text( ).
ENDTRY.
"Example 3
"Comparing the effect of CONV and EXACT
TYPES numtext TYPE n LENGTH 20.
TRY.
DATA(ex5) = EXACT numtext( '2 Apples + 5 Oranges' ).
CATCH cx_sy_conversion_error INTO DATA(e3).
DATA(t3) = e3->get_text( ).
ENDTRY.
DATA(conv_comp) = CONV numtext( '2 Apples + 5 Oranges' ).
IF ex1 IS INITIAL.
output->display( |ex2: { ex2 }; { t1 }| ).
ELSE.
output->display( ex1 ).
ENDIF.
IF ex3 IS INITIAL.
output->display( |ex4: { ex4 }; { t2 }| ).
ELSE.
output->display( input = ex3 name = `ex3` ).
ENDIF.
IF ex5 IS INITIAL.
output->display( input = t3 name = `t3` ).
ELSE.
output->display( input = ex5 name = `ex5` ).
ENDIF.
output->display( input = conv_comp name = `conv_comp` ).
**********************************************************************
output->next_section( `30) REF` ).
"The example includes the declaration of a data object and some data
"reference variables. One data reference variable is typed with a
"complete type, the other one is typed with a generic type. Then, data
"references to the data object declared before are created. Using the #
"symbol means that the type can be automatically derived.
"You can also use inline declarations to omit the explicit declaration.
"Another example shows the explicit specification of the data type after
"REF.
"Furthermore, an object reference is created using inline declaration.
"Declaring data object
DATA number TYPE i VALUE 5.
"Declaring data reference variables
DATA dref_a TYPE REF TO i. "Complete type
DATA dref_b TYPE REF TO data. "Generic type
"Creating data references to data objects
dref_a = REF #( number ).
dref_b = REF #( number ).
"Data reference variable declared inline
DATA(dref_c) = REF #( number ).
"Type specified explicitly
DATA(dref_d) = REF string( `hallo` ).
"Object references
DATA(oref_a) = NEW local_class( `Ciao` ).
DATA(oref_b) = REF #( oref_a ).
output->display( input = dref_a name = `dref_a` ).
output->display( input = dref_b name = `dref_b` ).
output->display( input = dref_c name = `dref_c` ).
output->display( input = dref_d name = `dref_d` ).
output->display( input = oref_b name = `oref_b` ).
**********************************************************************
output->next_section( `31) CAST` ).
"The example demonstrates the CAST operator in the context of Run Time
"Type Identification (RTTI).
"First, the components of a structure are retrieved. Secondly, the
"method information of a local class is retrieved. The syntax
"particularly shows the advantages of downcasts carried out with the
"CAST operator that also enables method chaining. An example is added
"that demonstrates the use of the older ?= operator with which extra
"variables are needed. Furthermore, simple downcasts are demonstrated
"using data references.
"RTTI examples
"Using CAST
"Retrieving structure components
DATA(components_s2) =
CAST cl_abap_structdescr(
cl_abap_typedescr=>describe_by_data( s2 ) )->components.
"Retrieving the methods of a local class
DATA(methods) =
CAST cl_abap_objectdescr(
cl_abap_objectdescr=>describe_by_name( 'LOCAL_CLASS' )
)->methods.
"Excursion: Using the older cast operator ?=
"Retrieving structure components
"Note: More lines of code, helper variables needed
DATA structdescr TYPE REF TO cl_abap_structdescr.
structdescr ?= cl_abap_typedescr=>describe_by_data( s1 ).
DATA(components_s1) = structdescr->components.
"Casting with data references
DATA dref_i TYPE REF TO i. "Complete type
DATA dref_data TYPE REF TO data. "Generic type
dref_data = NEW i( 123 ).
dref_i = CAST #( dref_data ).
output->display( input = components_s2 name = `components_s2` ).
output->display( input = methods name = `methods` ).
output->display( input = components_s1 name = `components_s1` ).
output->display( input = dref_i name = `dref_i` ).
**********************************************************************
output->next_section( `32) COND` ).
"The example demonstrates the use of the COND operator. The syntax
"includes several WHEN and THEN expressions.
"The example returns a string based on the current time.
DATA(syst_time) = cl_abap_context_info=>get_system_time( ).
DATA(greets) =
COND #( WHEN syst_time BETWEEN '050001' AND '120000'
THEN |It's { syst_time TIME = ISO }. | &&
|Good morning, { sy-uname }.|
WHEN syst_time BETWEEN '120001' AND '170000'
THEN |It's { syst_time TIME = ISO }. | &&
|Good afternoon, { sy-uname }.|
WHEN syst_time BETWEEN '170001' AND '210000'
THEN |It's { syst_time TIME = ISO }. | &&
|Good evening, { sy-uname }.|
WHEN syst_time BETWEEN '210001' AND '050000'
THEN |It's { syst_time TIME = ISO }. | &&
|Good night, { sy-uname }.|
ELSE |Hallo, { sy-uname }.|
).
output->display( input = greets name = `greets` ).