-
Notifications
You must be signed in to change notification settings - Fork 286
/
zcl_demo_abap_dynamic_prog.clas.abap
4816 lines (3761 loc) · 196 KB
/
zcl_demo_abap_dynamic_prog.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
"! <p class="shorttext"><strong>Dynamic programming</strong><br/>ABAP cheat sheet example class</p>
"!
"! <p>The example class demonstrates syntax and concepts related to dynamic programming.<br/>
"! Choose F9 in ADT to run the class.</p>
"!
"! <h2>Note</h2>
"! <ul><li>Topics covered: Field symbols and data references (both as supporting elements for dynamic
"! programming), dynamic ABAP syntax components, runtime type services (RTTS), i.e., runtime type
"! identification (RTTI) and runtime type creation (RTTC).</li>
"! <li>To provide true dynamic determination at runtime for several code examples in this class,
"! the example class includes local classes in the CCIMP include (local types tab in ADT) whose
"! methods return character-like content for use in ABAP statements. The content is predefined
"! in these classes, but the actual content used is random.</li>
"! <li>Find information on <strong>getting started with the example class</strong> and the
"! <strong>disclaimer</strong> in the ABAP Doc comment of class {@link zcl_demo_abap_aux}.</li></ul>
CLASS zcl_demo_abap_dynamic_prog DEFINITION
PUBLIC
FINAL
CREATE PUBLIC .
PUBLIC SECTION.
INTERFACES: if_oo_adt_classrun.
CLASS-METHODS:
class_constructor.
PROTECTED SECTION.
PRIVATE SECTION.
METHODS inst_meth1.
METHODS inst_meth2 IMPORTING text TYPE string
RETURNING VALUE(result) TYPE string.
CLASS-METHODS stat_meth1.
CLASS-METHODS stat_meth2 IMPORTING text TYPE string
EXPORTING result TYPE string.
ENDCLASS.
CLASS zcl_demo_abap_dynamic_prog IMPLEMENTATION.
METHOD class_constructor.
"Filling demo database tables.
zcl_demo_abap_aux=>fill_dbtabs( ).
ENDMETHOD.
METHOD if_oo_adt_classrun~main.
out->write( |ABAP Cheat Sheet Example: Dynamic Programming\n\n| ).
**********************************************************************
out->write( |Excursion: Field Symbols\n\n| ).
out->write( |1) Declaring Field Symbols\n\n| ).
"Some data declarations and type definitions used further down
DATA: str TYPE string.
TYPES: BEGIN OF struc, "Structured data type
num1 TYPE i,
num2 TYPE i,
END OF struc,
tab_type TYPE TABLE OF struc. "Internal table type
"Field symbol declarations
"- Name of the field symbol goes between angle brackets
"- Type: either a complete data type or a generic type.
"Complete types
"Here, a chained statement with a colon is used.
FIELD-SYMBOLS: <fs_i> TYPE i,
<fs_flsch> TYPE zdemo_abap_flsch,
<fs_tab_type> TYPE LINE OF tab_type,
<fs_like> LIKE str.
"Generic types
"There are plenty of options for generic ABAP types. Check the
"keyword docu.
FIELD-SYMBOLS <fs_c> TYPE c. "Text field with a generic length
FIELD-SYMBOLS <fs_cseq> TYPE csequence. "Text-like (c, string)
FIELD-SYMBOLS <fs_data> TYPE data. "Any data type
FIELD-SYMBOLS <fs_any_table> TYPE ANY TABLE. "Internal table with any table type
"Declaring field symbols inline
"Prominent use case: Inline declaration of a field symbol for an internal table
"following ASSIGNING.
DATA demo_itab TYPE TABLE OF zdemo_abap_flsch WITH EMPTY KEY.
LOOP AT demo_itab ASSIGNING FIELD-SYMBOL(<line>).
...
ENDLOOP.
out->write( zcl_demo_abap_aux=>no_output ).
**********************************************************************
out->write( zcl_demo_abap_aux=>heading( `2) Assigning Data Objects to Field Symbols` ) ).
"ASSIGN statements assigns the memory area of a data object to a field symbol.
"Once the memory area is assigned, you can work with the content.
"You can also assign a particular component of a structure. Either you
"specify the position of the component or the name of the component.
"Data objects.
DATA: num_a TYPE i,
struc_a TYPE zdemo_abap_fli,
tab_a TYPE string_table.
"Field symbols with complete types
FIELD-SYMBOLS: <fs_i_a> TYPE i,
<fs_struc_a> TYPE zdemo_abap_fli,
<fs_tab_a> TYPE string_table.
"Field symbols with generic types, see more examples bwloe
FIELD-SYMBOLS <fs_data_a> TYPE data.
FIELD-SYMBOLS <fs_anytab_a> TYPE ANY TABLE.
"Assigning data objects to field symbols
ASSIGN num_a TO <fs_i_a>.
ASSIGN struc_a TO <fs_struc_a>.
ASSIGN tab_a TO <fs_tab_a>.
ASSIGN: num_a TO <fs_data_a>,
struc_a TO <fs_data_a>,
tab_a TO <fs_data_a>,
tab_a TO <fs_anytab_a>.
"Inline declaration is possible, too. The field symbol is implicitly typed
"with the generic type data.
ASSIGN num_a TO FIELD-SYMBOL(<fs_inl>).
"Generic typing
"- Generic types are available with which formal parameters of methods or field symbols
" can be specified.
"- At runtime, the actual data type is copied from the assigned actual parameter or
" memory area, i.e. they receive the complete data type only when an actual parameter
" is passed or a memory area is assigned.
FIELD-SYMBOLS:
"Any data type
<data> TYPE data,
<any> TYPE any,
"Any data type can be assigned. Restrictions for formal parameters and 'data': no
"numeric functions, no description functions, and no arithmetic expressions can be
"passed to these parameters. However, you can bypass the restriction by applying the
"CONV operator for the actual parameter.
"Character-like types
<c> TYPE c, "Text field with a generic length
<clike> TYPE clike, "Character-like (c, n, string, d, t and character-like flat structures)
<csequence> TYPE csequence, "Text-like (c, string)
<n> TYPE n, "Numeric text with generic length
<x> TYPE x, "Byte field with generic length
<xsequence> TYPE xsequence, "Byte-like (x, xstring)
"Numeric types
<decfloat> TYPE decfloat, "decfloat16, decfloat34)
<numeric> TYPE numeric, "Numeric ((b, s), i, int8, p, decfloat16, decfloat34, f)
<p> TYPE p, "Packed number (generic length and number of decimal places)
"Internal table types
<any_table> TYPE ANY TABLE, "Internal table with any table type
<hashed_table> TYPE HASHED TABLE,
<index_table> TYPE INDEX TABLE,
<sorted_table> TYPE SORTED TABLE,
<standard_table> TYPE STANDARD TABLE,
<table> TYPE table, "Standard table
"Other types
<simple> TYPE simple, "Elementary data type including enumerated types and
"structured types with exclusively character-like flat components
<object> TYPE REF TO object. "object can only be specified after REF TO; can point to any object
"Data objects to work with
DATA: BEGIN OF s,
c3 TYPE c LENGTH 3,
c10 TYPE c LENGTH 10,
n4 TYPE n LENGTH 4,
str TYPE string,
time TYPE t,
date TYPE d,
dec16 TYPE decfloat16,
dec34 TYPE decfloat34,
int TYPE i,
pl4d2 TYPE p LENGTH 4 DECIMALS 2,
tab_std TYPE STANDARD TABLE OF string WITH EMPTY KEY,
tab_so TYPE SORTED TABLE OF string WITH NON-UNIQUE KEY table_line,
tab_ha TYPE HASHED TABLE OF string WITH UNIQUE KEY table_line,
xl1 TYPE x LENGTH 1,
xstr TYPE xstring,
structure TYPE zdemo_abap_carr, "character-like flat structure
oref TYPE REF TO object,
END OF s.
"The following static ASSIGN statements demonstrate various assignments
"Note:
"- The statements commented out show impossible assignments.
"- If a static assignment is not successful, sy-subrc is not set and no
" memory area is assigned. Dynamic assignments, however, set the value.
"----- Any data type -----
ASSIGN s-c3 TO <data>.
ASSIGN s-time TO <data>.
ASSIGN s-tab_std TO <data>.
ASSIGN s-xstr TO <any>.
ASSIGN s-pl4d2 TO <any>.
ASSIGN s-date TO <any>.
"----- Character-like types -----
ASSIGN s-c3 TO <c>.
ASSIGN s-c10 TO <c>.
"ASSIGN s-str TO <c>.
ASSIGN s-c10 TO <clike>.
ASSIGN s-str TO <clike>.
ASSIGN s-n4 TO <clike>.
ASSIGN s-date TO <clike>.
ASSIGN s-time TO <clike>.
ASSIGN s-structure TO <clike>.
ASSIGN s-c10 TO <csequence>.
ASSIGN s-str TO <csequence>.
"ASSIGN s-n4 TO <csequence>.
ASSIGN s-n4 TO <n>.
"ASSIGN s-int TO <n>.
"ASSIGN s-time TO <n>.
ASSIGN s-xl1 TO <x>.
"ASSIGN s-xstr TO <x>.
ASSIGN s-xl1 TO <xsequence>.
ASSIGN s-xstr TO <xsequence>.
"----- Numeric types -----
ASSIGN s-dec16 TO <numeric>.
ASSIGN s-dec34 TO <numeric>.
ASSIGN s-int TO <numeric>.
ASSIGN s-pl4d2 TO <numeric>.
"ASSIGN s-n4 TO <numeric>.
ASSIGN s-dec16 TO <decfloat>.
ASSIGN s-dec34 TO <decfloat>.
ASSIGN s-pl4d2 TO <p>.
"ASSIGN s-dec34 TO <p>.
"----- Internal table types -----
ASSIGN s-tab_std TO <any_table>.
ASSIGN s-tab_so TO <any_table>.
ASSIGN s-tab_ha TO <any_table>.
ASSIGN s-tab_std TO <index_table>.
ASSIGN s-tab_so TO <index_table>.
"ASSIGN s-tab_ha TO <index_table>.
"ASSIGN s-tab_std TO <sorted_table>.
ASSIGN s-tab_so TO <sorted_table>.
"ASSIGN s-tab_ha TO <sorted_table>.
ASSIGN s-tab_std TO <standard_table>.
ASSIGN s-tab_std TO <table>.
"ASSIGN s-tab_so TO <standard_table>.
"ASSIGN s-tab_so TO <table>.
"ASSIGN s-tab_ha TO <standard_table>.
"ASSIGN s-tab_ha TO <table>.
"ASSIGN s-tab_std TO <hashed_table>.
"ASSIGN s-tab_so TO <hashed_table>.
ASSIGN s-tab_ha TO <hashed_table>.
"----- Other types -----
ASSIGN s-c10 TO <simple>.
ASSIGN s-str TO <simple>.
ASSIGN s-dec34 TO <simple>.
ASSIGN s-date TO <simple>.
ASSIGN s-structure TO <simple>.
ASSIGN s-xl1 TO <simple>.
"ASSIGN s-tab_ha TO <simple>.
ASSIGN s-oref TO <object>.
s-oref = NEW zcl_demo_abap_objects( ).
ASSIGN s-oref TO <object>.
s-oref = cl_abap_random_int=>create( ).
ASSIGN s-oref TO <object>.
out->write( zcl_demo_abap_aux=>no_output ).
**********************************************************************
out->write( zcl_demo_abap_aux=>heading( `3) Checking Field Symbol Assignment` ) ).
"When working with field symbols, you should make sure that they are
"assigned. Otherwise, a runtime error occurs.
"You can make use of a logical expression with IS [NOT] ASSIGNED.
"The example includes data object declarations. One data object is
"assigned, the other is not. Consequently, the expression is
"true for the one and false for the other.
DATA num_b TYPE i VALUE 123.
FIELD-SYMBOLS: <fs_i_b> TYPE i,
<fs_str_b> TYPE string.
ASSIGN num_b TO <fs_i_b>.
IF <fs_i_b> IS ASSIGNED.
out->write( `Field symbol <fs_i_b> is assigned.` ).
ELSE.
out->write( `Field symbol <fs_i_b is> not assigned.` ).
ENDIF.
out->write( |\n| ).
IF <fs_str_b> IS ASSIGNED.
out->write( `Field symbol <fs_str_b> is assigned.` ).
ELSE.
out->write( `Field symbol <fs_str_b> is not assigned.` ).
ENDIF.
**********************************************************************
out->write( zcl_demo_abap_aux=>heading( `4) Unassigning Data Objects from Field Symbols` ) ).
"If you use an unassigned field symbol, an exception is raised. Before
"using it, you can check the assignment with the following logical
"expression. The statement is true if the field symbol is assigned.
"Using the statement UNASSIGN, you can explicitly remove the assignment
"of the field symbol.
DATA num_c TYPE i VALUE 123.
FIELD-SYMBOLS: <fs_i_c> TYPE i.
ASSIGN num_c TO <fs_i_c>.
IF <fs_i_c> IS ASSIGNED.
out->write( `1. Field symbol <fs_i_c> is assigned.` ).
ELSE.
out->write( `1. Field symbol <fs_i_c> is not assigned.` ).
ENDIF.
out->write( |\n| ).
UNASSIGN <fs_i_c>.
IF <fs_i_c> IS ASSIGNED.
out->write( `2. Field symbol <fs_i_c> is assigned.` ).
ELSE.
out->write( `2. Field symbol <fs_i_c> is not assigned.` ).
ENDIF.
**********************************************************************
out->write( zcl_demo_abap_aux=>heading( `5) Type Casting with Field Symbols` ) ).
"The example demonstrates the CASTING addition. Various additions after
"CASTING are possible.
TYPES type_d_l9 TYPE c LENGTH 9.
DATA: dobj_d_l5 TYPE c LENGTH 5,
dobj_d_l10 TYPE c LENGTH 10 VALUE '1234567890',
type_name_d TYPE string VALUE 'TYPE_D_L9'.
FIELD-SYMBOLS: <fs_d1> TYPE data,
<fs_d2> TYPE type_d_l9.
"Casting to a statically, completely specified type
"CASTING addition without any more additions: Field symbol inherits
"the data type of the data object. The field symbol must be either
"completely typed or with one of the generic built-in ABAP types
"c, n, p, or x. The other field symbol declared in the example
"cannot be used.
ASSIGN dobj_d_l10 TO <fs_d2> CASTING.
out->write( data = <fs_d2> name = `<fs_d2>` ).
out->write( |\n| ).
ASSIGN dobj_d_l10 TO <fs_d1> CASTING TYPE type_d_l9.
out->write( data = <fs_d1> name = `<fs_d1>` ).
out->write( |\n| ).
"Casting to a generic type
ASSIGN dobj_d_l10 TO <fs_d1> CASTING TYPE c.
out->write( data = <fs_d1> name = `<fs_d1>` ).
out->write( |\n| ).
"Casting to a static field type
ASSIGN dobj_d_l10 TO <fs_d1> CASTING LIKE dobj_d_l5.
out->write( data = <fs_d1> name = `<fs_d1>` ).
out->write( |\n| ).
"Casting to a dynamic field type
ASSIGN dobj_d_l10 TO <fs_d1> CASTING LIKE <fs_d1>.
out->write( data = <fs_d1> name = `<fs_d1>` ).
out->write( |\n| ).
"Anticipating dynamic specification of data types
"for the CASTING addition.
"The type name is specified as a character-like data
"object within parentheses.
ASSIGN dobj_d_l10 TO <fs_d1> CASTING TYPE (type_name_d).
out->write( data = <fs_d1> name = `<fs_d1>` ).
out->write( |\n| ).
"Anticipating RTTS
"A type description object is created which can be
"specified after the TYPE HANDLE additions.
DATA(sometype) = CAST cl_abap_datadescr(
cl_abap_typedescr=>describe_by_name( 'TYPE_D_L9' ) ).
ASSIGN dobj_d_l10 TO <fs_d1> CASTING TYPE HANDLE sometype.
out->write( data = <fs_d1> name = `<fs_d1>` ).
**********************************************************************
out->write( zcl_demo_abap_aux=>heading( `6) Addressing Field Symbols` ) ).
"The example includes multiple data objects that are assigned to field
"symbols. It is demonstrated that field symbols are addressed in various
"occasions. Among them: Changing the value of data objects assigned to
"field symbols, the use of field symbols in expressions, structures, and
"internal tables.
DATA: num_e TYPE i VALUE 456,
struc_e TYPE zdemo_abap_carr,
tab_e TYPE TABLE OF zdemo_abap_carr WITH EMPTY KEY.
SELECT SINGLE *
FROM zdemo_abap_carr
WHERE carrid = 'LH'
INTO @struc_e.
FIELD-SYMBOLS: <fs_i_e> TYPE i,
<fs_struc_e> TYPE zdemo_abap_carr,
<fs_tab_e> LIKE tab_e,
<fs_anytab_e> TYPE ANY TABLE.
"Without an assignment, this would result in a runtime error:
"<fs_i_e> = 1.
ASSIGN num_e TO <fs_i_e>.
ASSIGN struc_e TO <fs_struc_e>.
ASSIGN tab_e TO <fs_tab_e>.
ASSIGN tab_e TO <fs_anytab_e>.
"Changing values
<fs_i_e> = 789.
out->write( data = <fs_i_e> name = `<fs_i_e>` ).
out->write( |\n| ).
out->write( data = num_e name = `num_e` ).
out->write( |\n| ).
"Use in expressions
DATA(calc_e) = <fs_i_e> + 211.
out->write( data = calc_e name = `calc_e` ).
out->write( |\n| ).
IF <fs_i_e> < 1000.
out->write( `The value of <fs_i_e> is less than 1000` ).
ELSE.
out->write( `The value of <fs_i_e> is greater than 1000` ).
ENDIF.
out->write( |\n| ).
out->write( |\n| ).
"Structure
out->write( data = <fs_struc_e> name = `<fs_struc_e>` ).
out->write( |\n| ).
DATA(comp_e1) = <fs_struc_e>-carrid.
out->write( data = comp_e1 name = `comp_e1` ).
out->write( |\n| ).
<fs_struc_e>-url = 'www.lh.com'.
out->write( data = <fs_struc_e>-url name = `<fs_struc_e>-url` ).
out->write( |\n| ).
"Internal table
SELECT *
FROM zdemo_abap_carr
ORDER BY carrid
INTO TABLE @<fs_tab_e>
UP TO 3 ROWS.
out->write( data = <fs_tab_e> name = `<fs_tab_e>` ).
out->write( |\n| ).
TRY.
DATA(comp_e2) = <fs_tab_e>[ 2 ]-carrname.
out->write( data = comp_e2 name = `comp_e2` ).
CATCH cx_sy_itab_line_not_found INTO DATA(error_e).
ENDTRY.
out->write( |\n| ).
SELECT *
FROM zdemo_abap_carr
ORDER BY carrid
INTO TABLE @<fs_anytab_e>
UP TO 3 ROWS.
out->write( data = <fs_anytab_e> name = `<fs_anytab_e>` ).
**********************************************************************
out->write( zcl_demo_abap_aux=>heading( `7) Using Field Symbols when Processing Internal Tables` ) ).
"By using field symbols in the context of loops across internal tables,
"you can avoid an actual copying of content to a work area during
"the loop.
"The example includes multiple loops. First, internal tables are
"declared. One of them is filled. Then, field symbols are declared to
"which data objects are assigned. In the first loop, a previously
"declared field symbol is used as target area to hold the table line
"that is processed. In the course of the loop, some values are changed. The
"components are accessed using the component selector '-'. At the end of
"the loop, another internal table is filled using the currently
"processed line for the second loop. The second loop (the loop is
"carried out based on
"an internal table a field symbol points to) uses a directly declared
"field symbol using ASSIGNING FIELD-SYMBOL(<...>). Also here, some
"values are changed and another internal table is filled. This table
"is of a generic type. At the end, this internal table is output, too.
DATA: tab_f1 TYPE TABLE OF zdemo_abap_fli WITH EMPTY KEY,
tab_f2 LIKE tab_f1,
tab_f3 LIKE tab_f1.
SELECT *
FROM zdemo_abap_fli
ORDER BY carrid
INTO TABLE @tab_f1
UP TO 3 ROWS.
FIELD-SYMBOLS: <fs_struc_f> LIKE LINE OF tab_f1,
<fs_tab_f> LIKE tab_f1,
<fs_anytab_f> TYPE ANY TABLE.
ASSIGN tab_f2 TO <fs_tab_f>.
ASSIGN tab_f3 TO <fs_anytab_f>.
LOOP AT tab_f1 ASSIGNING <fs_struc_f>.
<fs_struc_f>-connid = '99'.
<fs_struc_f>-fldate = cl_abap_context_info=>get_system_date( ).
<fs_struc_f>-price = <fs_struc_f>-price + 100.
<fs_struc_f>-currency = 'EUR'.
CLEAR: <fs_struc_f>-paymentsum,
<fs_struc_f>-seatsocc,
<fs_struc_f>-seatsocc_b,
<fs_struc_f>-seatsocc_f.
"Filling another itab
<fs_tab_f> = VALUE #( BASE <fs_tab_f> ( <fs_struc_f> ) ).
ENDLOOP.
out->write( data = tab_f1 name = `tab_f1` ).
out->write( |\n| ).
"The following example shows a field symbol declared inline.
LOOP AT <fs_tab_f> ASSIGNING FIELD-SYMBOL(<fs_struc_f2>).
<fs_struc_f2>-connid = '100'.
<fs_struc_f2>-fldate = cl_abap_context_info=>get_system_date( ) + 1.
<fs_struc_f2>-price = <fs_struc_f2>-price - 50.
<fs_struc_f2>-currency = 'USD'.
"Filling another itab
<fs_anytab_f> = VALUE #( BASE <fs_anytab_f> ( <fs_struc_f2> ) ).
ENDLOOP.
out->write( data = <fs_tab_f> name = `<fs_tab_f>` ).
out->write( |\n| ).
out->write( data = <fs_anytab_f> name = `<fs_anytab_f>` ).
**********************************************************************
out->write( zcl_demo_abap_aux=>heading( `8) Structure Assigned to Field Symbol: Accessing Structure Components` ) ).
"In this example, all components of a structure are processed using
"field symbols and an ASSIGN COMPONENT ... OF STRUCTURE ... statement.
"First, a field symbol is declared with a generic type. A structure is
"filled with values from a demo table. The structure is assigned to the
"field symbol. Using a DO loop, all components are processed. The
"sy-index value represents the position of the component in the
"structure. Once all components have been processed (i. e. if sy-subrc
"does not return '0' for a sy-index value), the loop is exited. The output
"shows all components and their values.
"See more examples for accessing structure components below.
FIELD-SYMBOLS <comp> TYPE data.
DATA comp_tab TYPE string_table.
SELECT SINGLE carrid, carrname, currcode, url
FROM zdemo_abap_carr
WHERE carrid = 'LH'
INTO @DATA(struct).
FIELD-SYMBOLS <struct> TYPE data.
ASSIGN struct TO <struct>.
DO.
"sy-index represents the position of a structure component
ASSIGN <struct>-(sy-index) TO <comp>.
"Old syntax
"ASSIGN COMPONENT sy-index OF STRUCTURE <struct> TO <comp>.
IF sy-subrc <> 0.
"If all components are processed, the loop is exited.
EXIT.
ELSE.
out->write( |sy-index: { sy-index }, component content:| ).
out->write( <comp> ).
out->write( |\n| ).
ENDIF.
ENDDO.
**********************************************************************
out->write( zcl_demo_abap_aux=>heading( `Data References` ) ).
out->write( |9) Declaring Data References\n\n| ).
"Like field symbols, data reference variables can be declared with both
"a complete and a generic data type using DATA statements and the
"addition REF TO. The type after REF TO represents the static data type.
"The example shows multiple ways of declaring a data reference variable
"using both complete and generic data types.
DATA: some_string TYPE string.
TYPES: ref_type TYPE REF TO zdemo_abap_flsch.
DATA: ref_a1 TYPE REF TO i, "Complete data type
ref_a2 TYPE REF TO zdemo_abap_carr, "Complete data type
ref_a3 LIKE REF TO some_string,
ref_a4 LIKE ref_a1,
ref_a5 TYPE ref_type,
ref_a6 TYPE REF TO data. "Generic data type
out->write( zcl_demo_abap_aux=>no_output ).
**********************************************************************
out->write( zcl_demo_abap_aux=>heading( `10) Creating Data References ` &&
`to Existing Data Objects` ) ).
"The example includes data reference variables with both complete and
"generic type. When using the REF operator, the '#' sign means that the
"type is derived from the data object. You can also explicitly specify
"the data type after REF before the parenthesis. Within the parentheses,
"you can provide a value.
"Declaring data object
DATA number_b TYPE i VALUE 5.
"Declaring data reference variables
DATA ref_b1 TYPE REF TO i.
DATA ref_data_b TYPE REF TO data.
"Creating data references to data objects.
"The '#' sign means that the type is derived from the data object.
ref_b1 = REF #( number_b ).
ref_data_b = REF #( number_b ).
"You can also use inline declarations to omit the explicit declaration.
DATA(ref_b2) = REF #( number_b ).
"You can explicitly specify the data type after REF.
"DATA(ref_b3) = REF #( g ).
out->write( zcl_demo_abap_aux=>no_output ).
**********************************************************************
out->write( zcl_demo_abap_aux=>heading( `11) Dynamically Creating Data Objects at Runtime Using Static Type Definitions` ) ).
"The example code shows the creation of anonymous data objects. They
"can be created using the statement CREATE DATA, the instance operator
"NEW, or the addition NEW of the INTO clause in a SELECT statement.
"A data reference variable is expected when anonymous objects are
"declared. They cannot be addressed by a name (hence anonymous).
"Note:
"- The examples cover static type definitions. As shown further down,
" there are options to dynamically specify the type definitions.
"- To output the content of the data reference variables, they
" must be dereferenced first. The details are shown further down.
"CREATE DATA statements
"Note that there are many additions available. The examples show a selection.
"Behind TYPE and LIKE, the syntax offers the same possibilities as the DATA statement.
"Creating an anonymous data object with an implicit type.
"If neither of the additions TYPE or LIKE are specified, the data reference variable
"must be completely typed.
DATA dref_c1 TYPE REF TO string.
CREATE DATA dref_c1.
"Creating anonymous data objects with explicit data type specification.
"Data reference variable with a generic type to be used in the following examples
"for the anonymous data object.
DATA dref_c2 TYPE REF TO data.
"Elementary, built-in ABAP type
CREATE DATA dref_c2 TYPE p LENGTH 8 DECIMALS 3.
"Anomyous internal table ...
"using the LIKE addition to refer to an existing internal table
DATA itab_c TYPE TABLE OF zdemo_abap_carr.
CREATE DATA dref_c2 LIKE itab_c.
"by specifying the entire table type
CREATE DATA dref_c2 TYPE HASHED TABLE OF zdemo_abap_carr WITH UNIQUE KEY carrid.
"Anonymous structures
CREATE DATA dref_c2 LIKE LINE OF itab_c.
CREATE DATA dref_c2 TYPE zdemo_abap_carr.
"Creating reference variable
TYPES elem_type_c TYPE c LENGTH 3.
CREATE DATA dref_c2 TYPE REF TO elem_type_c.
"NEW operator
"- Works like CREATE DATA dref TYPE type statements and can be used in general
" expression positions.
"- Allows to assign values to the new anonymous data objects in parentheses
"Creating data reference variables
DATA: dref_c3 TYPE REF TO i,
dref_c4 TYPE REF TO data.
"# character after NEW if the data type can be identified completely
"instead of the explicit type specification (only non-generic types)
dref_c3 = NEW #( 123 ).
dref_c3 = NEW i( 456 ).
dref_c4 = NEW zdemo_abap_carr( ). "not assigning any values
dref_c4 = NEW string( `hi` ).
"Creating anonymous data objects inline
"In doing so, you can omit a prior declaration of a variable.
DATA(dref_c5) = NEW i( 789 ).
DATA(dref_c6) = NEW zdemo_abap_carr( carrid = 'AB' carrname = 'AB Airlines' ).
"ABAP SQL SELECT statements
"Using the NEW addition in the INTO clause, an anonymous data object
"can be created in place.
SELECT *
FROM zdemo_abap_carr
INTO TABLE NEW @DATA(dref_c7) "Internal table
UP TO 3 ROWS.
SELECT SINGLE *
FROM zdemo_abap_carr
WHERE carrid = 'LH'
INTO NEW @DATA(dref_c8). "Structure
out->write( data = dref_c6->* name = `dref_c6->*` ).
out->write( |\n| ).
out->write( data = dref_c7->* name = `dref_c7->*` ).
out->write( |\n| ).
out->write( data = dref_c8->* name = `dref_c8->*` ).
**********************************************************************
out->write( zcl_demo_abap_aux=>heading( `12) Data References and Assignments` ) ).
"Regarding the assignment, note that static types of both data
"reference variables must be compatible. As a result of an assignment,
"both the target reference variable and the source reference variable
"point to the same data object.
"Upcast/downcasts: For an assignment to work, the basic rule applies:
"The static type of the target reference variable must be more general
"than or the same as the dynamic type of the source reference variable.
"In the example below:
"Upcast: The target data reference variable is of generic type, the
"source variable is of complete type. The assignment is done with the
"assignment operator '='.
"Downcast: The target data reference variable is of complete type, the
"source variable is of generic type. The assignment is done with casting
"operators, either with the constructor operator CAST or the older ?=.
"Declaring data reference variables
DATA ref_d1 TYPE REF TO i.
DATA ref_d2 TYPE REF TO i.
ref_d1 = NEW #( 789 ).
"Assigning data reference
ref_d2 = ref_d1.
"Casting
"Complete type
DATA(ref_d3) = NEW i( 321 ).
"Generic type
DATA ref_data_d1 TYPE REF TO data.
"Upcast
ref_data_d1 = ref_d3.
"Downcasts
DATA ref_d5 TYPE REF TO i.
"Generic type
DATA ref_data_d2 TYPE REF TO data.
ref_data_d2 = NEW i( 654 ).
ref_d5 = CAST #( ref_data_d2 ).
ref_d5 ?= ref_data_d2.
out->write( data = ref_d2->* name = `ref_d2->*` ).
out->write( |\n| ).
out->write( data = ref_data_d1->* name = `ref_data_d1->*` ).
out->write( |\n| ).
out->write( data = ref_d5->* name = `ref_d5->*` ).
**********************************************************************
out->write( zcl_demo_abap_aux=>heading( `13) Addressing Data References ` ) ).
"Before addressing the content of data objects a data reference points
"to, you must dereference data reference variables. Use the
"dereferencing operator ->*.
"The example includes multiple occasions in which data reference are
"addressed: Changing the content of a referenced data object, the use in
"logical expressions, structures, and internal tables.
"Creating data reference variables and assigning values
DATA(ref_e1) = NEW i( 1 ).
DATA(ref_e2) = NEW zdemo_abap_carr( carrid = 'LH'
carrname = 'Lufthansa' ).
"Generic type
DATA ref_data_e TYPE REF TO data.
"Copying reference
ref_data_e = ref_e1.
"Addressing
"Variable receives the content.
DATA(some_num) = ref_e1->*.
out->write( data = ref_e1->* name = `ref_e1->*` ).
out->write( |\n| ).
"Content of referenced data object is changed
ref_e1->* = 10.
out->write( data = ref_e1->* name = `ref_e1->*` ).
out->write( |\n| ).
"Data reference used in a logical expression
IF ref_e1->* > 5.
out->write( `The value of ref_e1 is greater than 5.` ).
ELSE.
out->write( `The value of ref_e1 is lower than 5.` ).
ENDIF.
out->write( |\n| ).
"Dereferenced generic type
DATA(calc) = 1 + ref_data_e->*.
out->write( data = calc name = `calc` ).
out->write( |\n| ).
"Complete structure
DATA(struc) = ref_e2->*.
out->write( data = ref_e2->* name = `ref_e2->*` ).
out->write( |\n| ).
"Individual structure component
"When dereferencing a data reference variable that has a structured
"data type, you can use the component selector -> to address individual components.
DATA(carrid) = ref_e2->carrid.
ref_e2->carrid = 'UA'.
out->write( data = ref_e2->carrid name = `ref_e2->carrid` ).
out->write( |\n| ).
"The following syntax also works (dereferencing operator and the component selector).
ref_e2->*-carrname = 'United Airlines'.
out->write( data = ref_e2->*-carrname name = `ref_e2->*-carrname` ).
out->write( |\n| ).
**********************************************************************
out->write( zcl_demo_abap_aux=>heading( `14) Checking if Data Reference ` &&
`Can Be Dereferenced` ) ).
"You can check if a data reference can be dereferenced by using
"a logical expression with IS [NOT] BOUND.
"The example shows both a data reference that is bound and not bound.
DATA(ref_f1) = NEW string( `hello` ).
DATA ref_f2 TYPE REF TO i.
out->write( `IF statement:` ).
IF ref_f1 IS BOUND.
out->write( `ref_f1 is bound.` ).
ELSE.
out->write( `ref_f1 is not bound.` ).
ENDIF.
out->write( |\n| ).
out->write( `COND operator:` ).
DATA(is_bound) = COND #( WHEN ref_f1 IS BOUND THEN `ref_f1 is bound.` ELSE `ref_f1 is not bound.` ).
out->write( is_bound ).
out->write( |\n| ).
out->write( `IF statement:` ).
IF ref_f2 IS BOUND.
out->write( `ref_f2 is bound.` ).
ELSE.
out->write( `ref_f2 is not bound.` ).
ENDIF.
out->write( |\n| ).
out->write( `COND operator:` ).
is_bound = COND #( WHEN ref_f2 IS BOUND THEN `ref_f2 is bound.` ELSE `ref_f2 is not bound.` ).
out->write( is_bound ).
**********************************************************************
out->write( zcl_demo_abap_aux=>heading( `15) Explicitly Removing a Reference` ) ).
"Note that the garbage collector takes care of removing the references
"automatically once the data is not used any more by a reference.
DATA(ref_g1) = NEW string( `hello` ).
IF ref_g1 IS INITIAL.
out->write( `Before CLEAR: ref_g1 is initial.` ).
ELSE.
out->write( `Before CLEAR: ref_g1 is not intial.` ).
ENDIF.
out->write( |\n| ).
IF ref_g1 IS BOUND.
out->write( `Before CLEAR: ref_g1 is bound.` ).
ELSE.
out->write( `Before CLEAR: ref_g1 is not bound.` ).
ENDIF.
out->write( |\n| ).
CLEAR ref_g1.
IF ref_g1 IS INITIAL.
out->write( `After CLEAR: ref_g1 is initial.` ).
ELSE.
out->write( `After CLEAR: ref_g1 is not initial.` ).
ENDIF.
out->write( |\n| ).
IF ref_g1 IS BOUND.
out->write( `After CLEAR: ref_g1 is bound.` ).
ELSE.
out->write( `After CLEAR: ref_g1 is not bound.` ).
ENDIF.
**********************************************************************
out->write( zcl_demo_abap_aux=>heading( `16) Overwriting Data Reference Variables` ) ).
"A data reference variable is overwritten if a new object is created
"with a data reference variable already pointing to a data object
DATA ref_h1 TYPE REF TO data.
ref_h1 = NEW i( 111 ).
out->write( data = ref_h1->* name = `ref_h1->*` ).
out->write( |\n| ).
ref_h1 = NEW string( `ref_h1 overwritten.` ).
out->write( data = ref_h1->* name = `ref_h1->*` ).
**********************************************************************