Skip to end of metadata
Go to start of metadata

This page is solely intended to classify pages which:

  • can run in background (no User Interaction)
  • can run in all ABAP-based systems (S/4, C/4, R/3, etc.) - any version (some codes may not run on old or recent systems)

List of all pages

Pages at first level

List of all pages

Pages at first level

Description: Field Symbol can hold run time object of type any and Runtime Type identification which is part of Runtime Type services can help us to identify the type of objects at runtime, including dictionary types and classes / objects.

Below is the code snippet which will explain you the use of Field symbol at run time and different way to cast the data objects type and the usage of RTTI.

Field symbols can be declared with specific types or can be declared as generic type

Part I:  Generically typed field symbols will have the run time type based on the 'type of data object assigned'.

For e.g if you have following structure defined in your program

Step 1)  

DATA: BEGIN OF spfli_key,
        carrid TYPE s_carr_id,
        connid TYPE s_conn_id,
      END OF spfli_key.
 

Step 2)

and if you want to identify the components of the structure or type of the structure at runtime, then

DATA: descr_ref TYPE REF TO cl_abap_structdescr,
      wa_comp TYPE abap_compdescr.
 

cl_abap_structdescr is the class defined by SAP under RTTI to identify the structure and components of the structure at runtime.

Step 3) 

At some part of your program, you may assign any strucutre to field symbol as below.

spfli_key-carrid = 'AA'.
spfli_key-connid = 800.

ASSIGN spfli_key TO <fs_any>.
 

Step 4)  call the static method of t he class typedescr, and import the field symbol created. Loop throgh the components and identify the name of the component.

descr_ref ?= cl_abap_typedescr=>describe_by_data( <fs_any> ).

WRITE: ' Structure components at run time :' .
SKIP 2.
WRITE: ' Field symbol will hold the data object assigned :' .

LOOP AT  descr_ref->components INTO wa_comp.
  WRITE: wa_comp-name.
ENDLOOP.

UNASSIGN <fs_any>.
 

Part II:  Generically typed field symbols can be casted at runtime by using the keyword, 'CASTING TYPE'. Data object assigned to the field symbol, will be type casted based on the runtime type specified.

Step 1: Follow the steps as before. and cast the field symbol defined as any to  any particular type at runtime, using 'CASTING TYPE' .

ASSIGN obj_spfli TO <fs_any> CASTING TYPE spfli_type.

descr_ref ?= cl_abap_typedescr=>describe_by_data( <fs_any> ).

WRITE: ' Field symbol will read the data object assign as per the casted type :' .
SKIP 2.

LOOP AT  descr_ref->components INTO wa_comp.
  WRITE: wa_comp-name.
ENDLOOP.
 
Error rendering macro 'code': Invalid value specified for parameter 'com.atlassian.confluence.ext.code.render.InvalidValueException'
*----this program is aimed for converting a character into currency format

DATA: v_dcpfm    TYPE usr01-dcpfm,
      v_amount   TYPE bseg-wrbtr,
      v_char(16) TYPE c.

SELECT SINGLE dcpfm FROM usr01
                    INTO v_dcpfm
                   WHERE bname = sy-uname.
IF v_dcpfm = 'X'.
*-- decimal point is '.' and thousands separator is ','
  TRANSLATE v_char USING ', '.
  CONDENSE v_char NO-GAPS.
  v_amount = v_char.
ELSEIF v_dcpfm = 'Y'.
*-- decimal point is ',' and thousands separator is '.'
  TRANSLATE v_char USING '. '.
  CONDENSE v_char NO-GAPS.
  v_amount = v_char.
ELSE.
*-- decimal point is ',' and thousands separator is space
  CONDENSE v_char NO-GAPS.
  v_amount = v_char.
ENDIF.

we can also use this function module HRCM_STRING_TO_AMOUNT_CONVERT


List of all pages

Pages at first level

*-------------------------------------------------------*
*  report name
*-------------------------------------------------------*

REPORT zchange_of_case .

*-------------------------------------------------------*
*   selection screen parameters
*------------------------------------------------------*

PARAMETERS: P_STR TYPE CHAR100 .

*-------------------------------------------------------*
*      data declarations
*------------------------------------------------------*

DATA: STRING TYPE CHAR100 .

*-------------------------------------------------------*
*    initialization
*------------------------------------------------------*

INITIALIZATION .

P_STR = 'THIS IS THE TEST' .

*-------------------------------------------------------*
*  start of selection
*------------------------------------------------------*

START-OF-SELECTION .

CALL FUNCTION 'STRING_UPPER_LOWER_CASE'
  EXPORTING
    delimiter = ' '
    string1   = P_STR
  IMPORTING
    STRING    = STRING
  EXCEPTIONS
    NOT_VALID = 1
    TOO_LONG  = 2
    TOO_SMALL = 3
    OTHERS    = 4.

IF sy-subrc <> 0.
MESSAGE ID SY-MSGID TYPE SY-MSGTY NUMBER SY-MSGNO
WITH SY-MSGV1 SY-MSGV2 SY-MSGV3 SY-MSGV4.
ENDIF.

*------output
	WRITE:/ STRING .

Go to SE37

Enter Name < NN_TEXT_CONVERT_PROPER>

Press Create Button

Enter Import & Export Variables as Type String

Enter Exceptions as      NOT_VALID

                                    TOO_LONG

                                    TOO_SMALL  
Create Source Code as Follows

Error rendering macro 'code': Invalid value specified for parameter 'com.atlassian.confluence.ext.code.render.InvalidValueException'
FUNCTION nn_text_convert_proper.
*"----------------------------------------------------------------------
*"*"Local Interface:
*"  IMPORTING
*"     REFERENCE(STRING1)
*"  EXPORTING
*"     REFERENCE(STRING)
*"  EXCEPTIONS
*"      NOT_VALID
*"      TOO_LONG
*"      TOO_SMALL
*"----------------------------------------------------------------------

  DATA  :
        it_txts      TYPE TABLE OF string,  "Tabel for data storing
        wa_txts(100) TYPE c,                "Getting each words
        cp_text      TYPE string,           "Copying text
        nn_text      TYPE string.           "Result text

  cp_text = string1.
  SPLIT cp_text AT space INTO: TABLE it_txts.

  LOOP AT it_txts INTO wa_txts.
    PERFORM  change_case USING wa_txts.
    CONCATENATE nn_text wa_txts INTO nn_text SEPARATED BY space.
  ENDLOOP.
  CONDENSE nn_text.
*
  CASE sy-subrc.
    WHEN 0.
      string = nn_text.
      EXIT.
    WHEN 2.
      RAISE not_valid.
    WHEN 3.
      RAISE too_long.
    WHEN 4.
      RAISE too_small.
  ENDCASE.

ENDFUNCTION.

*in the perform part add code as follows (include lzpropertop)

FUNCTION-POOL zproper.                      "MESSAGE-ID ..

*&---------------------------------------------------------------------*
*&      Form  CHANGE_CASE
*&---------------------------------------------------------------------*
FORM change_case  USING  p_wa_txts.

  DATA : p_dem.

  p_dem = '&'.

  CALL FUNCTION 'STRING_UPPER_LOWER_CASE'
    EXPORTING
      delimiter = p_dem
      string1   = p_wa_txts
    IMPORTING
      string    = p_wa_txts
    EXCEPTIONS
      not_valid = 1
      too_long  = 2
      too_small = 3
      OTHERS    = 4.
ENDFORM.                    " CHANGE_CASE
Error rendering macro 'code': Invalid value specified for parameter 'com.atlassian.confluence.ext.code.render.InvalidValueException'
*----this is the report for concatenating 2 strings

REPORT  zconcatenate_fm                         .

DATA: string(100) TYPE c.

PARAMETERS: abc(15) TYPE c,
            bbc(15) TYPE c.

CALL FUNCTION 'STRING_CONCATENATE'
  EXPORTING
    string1   = abc
    string2   = bbc
  IMPORTING
    string    = string
  EXCEPTIONS
    too_small = 1
    OTHERS    = 2.
IF sy-subrc <> 0.
  MESSAGE ID sy-msgid TYPE sy-msgty NUMBER sy-msgno
          WITH sy-msgv1 sy-msgv2 sy-msgv3 sy-msgv4.
ENDIF.

WRITE:/ string.

*----------------------------------------------------------------*
*  this is the report for concatenating 3 strings
*--------------------------------------------------------------*
REPORT  zconcatenate_fm01   .

DATA: string(50) TYPE c.

PARAMETERS: p_strng1(15) TYPE c,
            p_strng2(15) TYPE c,
            p_strng3(15) TYPE c.

CALL FUNCTION 'STRING_CONCATENATE_3'
  EXPORTING
    string1   = p_strng1
    string2   = p_strng2
    string3   = p_strng3
  IMPORTING
    string    = string
  EXCEPTIONS
    too_small = 1
    OTHERS    = 2.
IF sy-subrc <> 0.
  MESSAGE ID sy-msgid TYPE sy-msgty NUMBER sy-msgno
          WITH sy-msgv1 sy-msgv2 sy-msgv3 sy-msgv4.
ENDIF.

WRITE:/ string.

Method 1

PARAMETERS inp(40) DEFAULT 'Habitación' LOWER CASE.

DATA: BEGIN OF uml,
  um1 VALUE 'ó',
  um1_e VALUE 'o',
  um2 VALUE 'ä',
  um2_e VALUE 'a',
  um7 VALUE 'ß',
  um7_e(2) VALUE 'ss',
 END OF uml.

FIELD-SYMBOLS: <h1_string>, <h2_string>.
DATA string TYPE string.
DATA outp(40).
DATA: zaehler TYPE i VALUE 1.

string = inp.

DO.
  ASSIGN COMPONENT zaehler OF STRUCTURE uml TO <h1_string>.
  IF sy-subrc  NE 0.
    EXIT.
  ENDIF.
  zaehler = zaehler + 1.
  ASSIGN COMPONENT zaehler OF STRUCTURE uml TO <h2_string>.
  IF sy-subrc  NE 0.
    MESSAGE e000(yp).
  ENDIF.
  IF string CA <h1_string>.
    sy-subrc = 0.
    WHILE sy-subrc = 0.
      REPLACE <h1_string> WITH <h2_string> INTO string.
    ENDWHILE.
  ENDIF.
  zaehler = zaehler + 1.
ENDDO.

WRITE: inp, / string.
 

Method 2

PARAMETERS inp(40) DEFAULT 'Habitación' LOWER CASE.

DATA: outtext TYPE char40 .

CALL FUNCTION 'SCP_REPLACE_STRANGE_CHARS'
  EXPORTING
    intext  = inp
  IMPORTING
    outtext = outtext.

WRITE:/ outtext.
 

This code explains that how we can find the length of a string using the oops class using Static and instance method.

The  "methods" statement declares or redefines an instance method "get_strlen".

Instance methods are linked to Objects.

To use instance methods,we have to create an object of the class.

By Instance method we can access all components of the own class without using a component selector.

REPORT ztest_prem
     NO STANDARD PAGE HEADING LINE-SIZE 255.

DATA:  string_in  TYPE string,
       len_out TYPE i.

*----------------------------------------------------------------------*
*       CLASS string_op DEFINITION
*----------------------------------------------------------------------*
CLASS string_op DEFINITION.

  PUBLIC SECTION.
    METHODS : get_strlen IMPORTING value(str1) TYPE string
                         EXPORTING value(len1) TYPE i.


    METHODS : constructor.


    CLASS-METHODS : write_len.

**The CLASS-METHODS statement declares a static method.
* With the class component selector (=>), static methods can be used independently of objects.
*By static methods, we can only access the static components of the class or its
*superclasses

ENDCLASS.                    "string_op DEFINITION

DATA :  inst TYPE REF TO string_op.

CREATE OBJECT inst.

string_in = 'Premraj'.

CALL METHOD inst->get_strlen     "Calling of Instance method.
EXPORTING
   str1 = string_in
IMPORTING
   len1 = len_out.

CALL METHOD string_op=>write_len.   "Calling of Staic method.

*----------------------------------------------------------------------*
*       CLASS string_op IMPLEMENTATION
*----------------------------------------------------------------------*
CLASS string_op IMPLEMENTATION.

  METHOD get_strlen.
    len1 = strlen( str1 ).
  ENDMETHOD.                    "get_strlen

  METHOD write_len.
    WRITE : len_out.
  ENDMETHOD.                    "write_len

  METHOD constructor.
    WRITE : 'The length of String is :'.
  ENDMETHOD.                    "constructor

ENDCLASS.                    "string_op IMPLEMENTATION
 

Author: Jay Sadaram
Submitted: 11/07/2008
Description: In a SAP script I had some long text,which I was getting from Read_text function module. I had to split it and show in various lines. When the code was originally developed they were using the FM RKD_WORD_WRAP which splits to 3 lines Only, but my requirement was to have more than 10+ lines. So I developed a logic where with min changes you can adjust the number of characters to split to.. and kind of dynamic approach.

DATA: lv_len TYPE i,
      lv_z1 TYPE i,
      lv_z2 TYPE i,
      lv_z3 TYPE i,
      lv_z4 TYPE i,
      lv_z5 TYPE i,
      lv_z6 TYPE i,
      lv_z7 TYPE i,
      lv_last TYPE i,
      lv_offset(3) TYPE n.

lv_len = strlen( ztext ).
CLEAR: lv_offset.
lv_offset = lv_len / 7 .
lv_z1 = lv_offset.
lv_z2 = lv_z1 + 1.
lv_z3 = lv_z2 + lv_z1 + 1.
lv_z4 = lv_z3 + lv_z1 + 1.
lv_z5 = lv_z4 + lv_z1 + 1.
lv_z6 = lv_z5 + lv_z1 + 1.
lv_z7 = lv_z6 + lv_z1 + 1.
zoutline1 = ztext+0(lv_z1).
zoutline2 = ztext+lv_z2(lv_z1).
zoutline3 = ztext+lv_z3(lv_z1).
zoutline4 = ztext+lv_z4(lv_z1).
zoutline5 = ztext+lv_z5(lv_z1).
zoutline6 = ztext+lv_z6(lv_z1).
CHECK lv_len GT lv_z7.
lv_last = abs( lv_len - lv_z7 ).
zoutline7 = ztext+lv_z7(lv_last).
 

Here is a sample code where datatype 'N' accepts alphabets.

REPORT zconvert.
DATA :
w_date TYPE d , " Variable of type D
w_num(6) TYPE n . " Variable of type N

w_date = 'ABC123' .
MOVE w_date TO w_num .
SKIP 2 .
WRITE :25 w_num .

 In this case datatype 'N' accepts characters.





Factorial Calculation using Macro.

This program calculates the factorials of first 5 numbers using a macro.
Display the output in the following format using another macro.

Factorial of 1 is 1.
Factorial of 2 is 2.
Factorial of 3 is 6.
Factorial of 4 is 24.
Factorial of 5 is 120.

Error rendering macro 'code': Invalid value specified for parameter 'com.atlassian.confluence.ext.code.render.InvalidValueException'
REPORT zmacro.
* Work variables
DATA:
  w_num TYPE i VALUE 1,                " First number
  w_num1 TYPE i VALUE 5,               " Last Number
  w_fact TYPE i VALUE 1.               " Factorial Value
* Definition of Macro to Perform Factorial of first 5 numbers
DEFINE factorial.
  while &1 <= &2.
    &3 = &3 * &1.
    output &1 &3.
    add 1 to &1.
  endwhile.
END-OF-DEFINITION.                     " DEFINITION FACTORIAL
* Definition of Macro to Display the factorial result
DEFINE output.
  write:/ 'Factorial of', &1,'is', &2.
END-OF-DEFINITION.                     " DEFINITION OUTPUT

factorial w_num w_num1 w_fact.

Author: Jatra Riwayanto
Submitted: 06.06.2007

Description:
There is a time that we need to encode our data before we save it to database table.
I try encoded and decoded string data using method IF_HTTP_UTILITY~DECODE_BASE64 and IF_HTTP_UTILITY~ENCODE_BASE64 in class CL_HTTP_UTILITY.

Here the snippet:

Error rendering macro 'code': Invalid value specified for parameter 'com.atlassian.confluence.ext.code.render.InvalidValueException'
DATA: encoded   TYPE string,
      unencoded TYPE string.

START-OF-SELECTION.

  unencoded = 'This is test value'.
  WRITE: / 'Unencoded string:',  unencoded.

  encoded = cl_http_utility=>if_http_utility~encode_base64( unencoded = unencoded ).
  WRITE: / 'Encoded string:',  encoded.

  CLEAR: unencoded.
  unencoded = cl_http_utility=>if_http_utility~decode_base64( encoded = encoded ).
  WRITE: / 'Unencoded string:',  unencoded.

Result:

Author: JNN
Submitted: April 2nd 2014
Related Links:

Error rendering macro 'code': Invalid value specified for parameter 'com.atlassian.confluence.ext.code.render.InvalidValueException'
REPORT zz_buffer3.


CLASS lcx_buffer_error DEFINITION INHERITING FROM cx_static_check.
ENDCLASS.                    "lcx_buffer_error DEFINITION


CLASS lcx_buffer_key_in_buffer DEFINITION INHERITING FROM lcx_buffer_error.
ENDCLASS.                    "lcx_buffer_key_in_buffer DEFINITION


CLASS lcx_iterator_error DEFINITION INHERITING FROM lcx_buffer_error.
ENDCLASS.


CLASS lcx_buffer_value_not_found DEFINITION INHERITING FROM lcx_buffer_error.
ENDCLASS.                    "lcx_buffer_value_not_found DEFINITION


INTERFACE lif_unit_test.
ENDINTERFACE.


*----------------------------------------------------------------------*
*       CLASS lcl_table_buffer DEFINITION
*----------------------------------------------------------------------*
CLASS lcl_table_buffer DEFINITION CREATE PRIVATE FRIENDS lif_unit_test.


  PUBLIC SECTION.
    TYPES tt_fieldname TYPE STANDARD TABLE OF fieldname.
*   create a table buffer
    CLASS-METHODS factory
      IMPORTING iv_text TYPE csequence      " Unique ID, used for caching
                iv_value TYPE any           " any structure
                iv_key TYPE fieldname       " name of key field in structure
                it_keys TYPE tt_fieldname OPTIONAL  " (or all key fields) - not tested
      RETURNING value(ro_buffer) TYPE REF TO lcl_table_buffer
      RAISING lcx_buffer_error.
    METHODS put                             " put structure value in buffer
      IMPORTING iv_value TYPE any
      RAISING lcx_buffer_key_in_buffer .
    METHODS get                             " get value from buffer according to key
      IMPORTING iv_key TYPE simple
      EXPORTING ev_value TYPE data
      RAISING lcx_buffer_value_not_found.
    METHODS size                            " number of entries in buffer
      RETURNING value(rv_size) TYPE syindex.
    METHODS isempty                         " is the buffer empty?
      RETURNING value(rv_empty) TYPE flag.
    METHODS contains_key                    " is there a value with this key in buffer?
      IMPORTING iv_key TYPE simple
      RETURNING value(rv_idx) TYPE syindex.
    METHODS contains                       " is this value in the buffer ?
      IMPORTING iv_value TYPE data
      RETURNING value(rv_idx) TYPE syindex.
    METHODS delete                         " remove value with key from buffer
      IMPORTING iv_key TYPE simple
      RETURNING value(rv_found) TYPE flag.
    METHODS clear.                          " clear/empty the buffer
    CLASS-METHODS free
      IMPORTING iv_text TYPE csequence OPTIONAL.


  PRIVATE SECTION.
    DATA mv_key TYPE fieldname.
    DATA mr_buffer TYPE REF TO data.
    TYPES: BEGIN OF ts_map,
             name TYPE string,
             buffer TYPE REF TO lcl_table_buffer,
           END OF ts_map.
    CLASS-DATA gt_map TYPE SORTED TABLE OF ts_map
      WITH UNIQUE KEY name.
    METHODS constructor
      IMPORTING it_keys TYPE tt_fieldname
                is_struct TYPE any
      RAISING lcx_buffer_error.
ENDCLASS.


*----------------------------------------------------------------------*
*       CLASS lcl_table_buffer IMPLEMENTATION
*----------------------------------------------------------------------*
CLASS lcl_table_buffer IMPLEMENTATION.


  METHOD factory.
    DATA ls_map TYPE ts_map.
    DATA lt_keys TYPE tt_fieldname.
    IF it_keys IS INITIAL.
      APPEND iv_key TO lt_keys.
    ELSE.
      lt_keys = it_keys.
    ENDIF.
    READ TABLE gt_map INTO ls_map
      WITH KEY name = iv_text.
    IF sy-subrc NE 0.
      CREATE OBJECT ls_map-buffer
        EXPORTING it_keys = lt_keys
                  is_struct = iv_value.
      ls_map-name = iv_text.
      INSERT ls_map INTO TABLE gt_map.
    ENDIF.
    ro_buffer = ls_map-buffer.
  ENDMETHOD.                    "create


  METHOD constructor.
    FIELD-SYMBOLS <lv_comp> TYPE any.
    FIELD-SYMBOLS <ls_struct> TYPE any.
    FIELD-SYMBOLS <lv_key> TYPE fieldname.
    super->constructor( ).
    LOOP AT it_keys ASSIGNING <lv_key>.
      AT FIRST.
        mv_key = <lv_key>.
      ENDAT.
      ASSIGN COMPONENT <lv_key> OF STRUCTURE is_struct TO <lv_comp>.
      CHECK sy-subrc NE 0.
      RAISE EXCEPTION TYPE lcx_buffer_error.
    ENDLOOP.
    CREATE DATA mr_buffer LIKE SORTED TABLE OF is_struct
      WITH UNIQUE KEY (it_keys).
  ENDMETHOD.


  METHOD free.
    DATA ls_map TYPE ts_map.
    READ TABLE gt_map INTO ls_map
      WITH KEY name = iv_text.
    IF sy-subrc EQ 0.
      DELETE gt_map INDEX sy-index.
      FREE ls_map-buffer.
    ELSEIF iv_text IS INITIAL.
      CLEAR gt_map.
    ENDIF.
  ENDMETHOD.


  METHOD clear.
    CLEAR mr_buffer.
  ENDMETHOD.


  DEFINE assign_buffer.
    FIELD-SYMBOLS <lt_buffer> TYPE SORTED TABLE.
    ASSIGN mr_buffer->* TO <lt_buffer>.
    CHECK <lt_buffer> IS ASSIGNED.
  END-OF-DEFINITION.


  METHOD size.
    CLEAR rv_size.
    assign_buffer.
    rv_size = lines( <lt_buffer> ).
  ENDMETHOD.                    "size


  METHOD isempty.
    rv_empty = abap_true.
    assign_buffer.
    IF <lt_buffer> IS NOT INITIAL.
      rv_empty = abap_false.
    ENDIF.
  ENDMETHOD.                    "isEmpty


  METHOD contains_key.
*   Search for already buffered value
    CLEAR rv_idx.
    assign_buffer.
    READ TABLE <lt_buffer> TRANSPORTING NO FIELDS
      WITH TABLE KEY (mv_key) = iv_key.
    CHECK sy-subrc EQ 0.
    rv_idx = sy-tabix.
  ENDMETHOD.                    "contains_key


  METHOD contains.
*   Search for already buffered value
    CLEAR rv_idx.
    assign_buffer.
    READ TABLE <lt_buffer> TRANSPORTING NO FIELDS
      FROM iv_value.
    CHECK sy-subrc EQ 0.
    rv_idx = sy-tabix.
  ENDMETHOD.                    "contains

  METHOD get.
    FIELD-SYMBOLS <ls_data> TYPE any.
    assign_buffer.
    READ TABLE <lt_buffer> ASSIGNING <ls_data>
      WITH KEY (mv_key) = iv_key.
    IF sy-subrc NE 0.
*     Value was not found
      RAISE EXCEPTION TYPE lcx_buffer_value_not_found.
    ELSE.
      ev_value = <ls_data>.
    ENDIF.
  ENDMETHOD.                    "GET
  
  METHOD put.
*   Search for already buffered value
    FIELD-SYMBOLS <ls_data> TYPE any.
    assign_buffer.
    READ TABLE <lt_buffer> ASSIGNING <ls_data>
      FROM iv_value.
    IF sy-subrc EQ 0.
*     key was already in the buffer
      RAISE EXCEPTION TYPE lcx_buffer_key_in_buffer.
    ELSE.
*     Value was not found, insert:
      INSERT iv_value INTO TABLE <lt_buffer>.
    ENDIF.
  ENDMETHOD.                    "insert


  METHOD delete.
*   remove existing entry - not tested yet
    FIELD-SYMBOLS <ls_data> TYPE any.
    assign_buffer.
    DELETE TABLE <lt_buffer>
      WITH TABLE KEY (mv_key) = iv_key.
  ENDMETHOD.                    "insert
ENDCLASS.


*----------------------------------------------------------------------*
*       CLASS lcl_test DEFINITION
*----------------------------------------------------------------------*
CLASS lcl_test DEFINITION FOR TESTING
  DURATION MEDIUM RISK LEVEL HARMLESS.
  PUBLIC SECTION.
    INTERFACES lif_unit_test.
  PRIVATE SECTION.
    CONSTANTS c_max_size TYPE i VALUE 1000.
    CONSTANTS c_text_save TYPE char40 VALUE 'SAVE_BUFFER_TEST'.
    DATA mv_sbook_size TYPE i.
    DATA mv_buffer_size TYPE i.
    DATA mt_sbook TYPE STANDARD TABLE OF sbook.
    DATA mv_start TYPE i.
    DATA mv_time TYPE i.
    DATA mi_timer TYPE REF TO IF_ABAP_RUNTIME.


    METHODS setup.
    METHODS without_buffer FOR TESTING.
    METHODS filling_buffer FOR TESTING.
    METHODS select_without_buffer
      RETURNING VALUE(rv_counter) TYPE i.
    METHODS select_with_buffer
      RETURNING VALUE(ro_buffer) TYPE REF TO lcl_table_buffer
      RAISING lcx_buffer_error.
    METHODS from_buffer
      RAISING lcx_buffer_error.
    METHODS start_timer.
    METHODS stop_timer RETURNING VALUE(rv_time) TYPE i.
    METHODS buffer_runtime FOR TESTING.
    METHODS save_buffer FOR TESTING.
    METHODS contains FOR TESTING.
ENDCLASS.                    "lcl_test DEFINITION


*----------------------------------------------------------------------*
*       CLASS lcl_test IMPLEMENTATION
*----------------------------------------------------------------------*
CLASS lcl_test IMPLEMENTATION.


  METHOD setup.
    DATA lt_customid TYPE STANDARD TABLE OF sbook-customid.
    SELECT * FROM sbook INTO TABLE mt_sbook
      UP TO c_max_size ROWS.
    SELECT customid FROM sbook
      INTO TABLE lt_customid
      FOR ALL ENTRIES IN mt_sbook
      WHERE carrid = mt_sbook-carrid
        AND connid = mt_sbook-connid
        AND fldate = mt_sbook-fldate
        AND bookid = mt_sbook-bookid.
      mv_buffer_size = lines( lt_customid ).
      mv_sbook_size = lines( mt_sbook ).
      mi_timer = cl_abap_runtime=>create_hr_timer( ).
    ENDMETHOD.                    "query_sbook


    METHOD start_timer.
      mv_start = mi_timer->get_runtime( ).
    ENDMETHOD.


    METHOD stop_timer.
      rv_time = mi_timer->get_runtime( ) - mv_start.
    ENDMETHOD.


    METHOD select_without_buffer.
      DATA ls_sbuspart TYPE sbuspart.
      DATA ls_sbook TYPE sbook.
      CLEAR rv_counter.
      LOOP AT mt_sbook INTO ls_sbook.
        SELECT SINGLE * FROM sbuspart INTO ls_sbuspart
          WHERE buspartnum = ls_sbook-customid.
        ADD 1 TO rv_counter.
      ENDLOOP.
    ENDMETHOD.


    METHOD without_buffer.
      DATA lv_counter TYPE i.
      lv_counter = select_without_buffer( ).
      cl_aunit_assert=>assert_equals( exp = mv_sbook_size
                                      act = lv_counter
                                      msg = 'WITHOUT_BUFFER error' ).
    ENDMETHOD.                    "without_buffer


    METHOD select_with_buffer.
      DATA ls_sbuspart TYPE sbuspart.
      DATA ls_sbook TYPE sbook.
      ro_buffer = lcl_table_buffer=>factory(
        iv_text = 'CUSTOMER_DETAILS'
        iv_value = ls_sbuspart      " structure
        iv_key = 'BUSPARTNUM' ).
      LOOP AT mt_sbook INTO ls_sbook.
        CHECK ro_buffer->contains_key( ls_sbook-customid ) EQ 0.
*       If we haven't saved it yet, get it and save it
        SELECT SINGLE * FROM sbuspart INTO ls_sbuspart
          WHERE buspartnum = ls_sbook-customid.
        ro_buffer->put( ls_sbuspart ).
      ENDLOOP.
    ENDMETHOD.


    METHOD filling_buffer.
      DATA lo_buffer TYPE REF TO lcl_table_buffer.
      DATA lx_error TYPE REF TO cx_static_check.
      DATA lv_counter TYPE i.
      TRY.
          lo_buffer = select_with_buffer( ).
          lv_counter = lo_buffer->size( ).
          cl_aunit_assert=>assert_equals( exp = mv_buffer_size
                                          act = lv_counter
                                          msg = 'WITH_BUFFER error' ).
        CATCH lcx_buffer_error INTO lx_error.
          cl_aunit_assert=>fail( msg = | WITH_BUFFER { lx_error->get_text( ) } |  ).
      ENDTRY.
    ENDMETHOD.                    "with_buffer


    METHOD from_buffer.
      DATA lo_buffer TYPE REF TO lcl_table_buffer.
      DATA lx_error TYPE REF TO cx_static_check.
      DATA lv_counter TYPE i.
      DATA ls_sbuspart TYPE sbuspart.
      DATA ls_sbook TYPE sbook.
      lo_buffer = lcl_table_buffer=>factory(
        iv_text = 'CUSTOMER_DETAILS'
        iv_value = ls_sbuspart      " structure
        iv_key = 'BUSPARTNUM' ).
      TRY.
          LOOP AT mt_sbook INTO ls_sbook.
            lo_buffer->get( ls_sbook-customid ).
            ADD 1 to lv_counter.
          ENDLOOP.
        CATCH lcx_buffer_error INTO lx_error.
          cl_aunit_assert=>fail( msg = | ITERATOR { lx_error->get_text( ) } |  ).
      ENDTRY.
    ENDMETHOD.


    METHOD buffer_runtime.
      DATA lx_error TYPE REF TO cx_static_check.
      DATA lv_time_from_buffer TYPE i.
      DATA lv_time_fill_buffer TYPE i.
      DATA lv_time_wo_buffer TYPE i.
      DATA lv_flag TYPE flag.
      start_timer( ).
      select_without_buffer( ).
      lv_time_wo_buffer = stop_timer( ).
      start_timer( ).
      TRY.
          select_with_buffer( ).
          lv_time_fill_buffer = stop_timer( ).
          start_timer( ).
          from_buffer( ).
          lv_time_from_buffer = stop_timer( ).
          IF lv_time_fill_buffer LT lv_time_wo_buffer.
            lv_flag = 'X'.
          ELSE.
            lv_flag = space.
          ENDIF.
          cl_abap_unit_assert=>assert_equals(
            exp = 'X'
            act = lv_flag
            level = if_aunit_constants=>tolerable
            msg = |RUN TIME fill buffer: { lv_time_fill_buffer } w/o buffer: { lv_time_wo_buffer } from buffer: { lv_time_from_buffer } | ).
        CATCH lcx_buffer_error INTO lx_error.
          cl_aunit_assert=>fail( msg = | RUN TIME { lx_error->get_text( ) } |  ).
      ENDTRY.
    ENDMETHOD.                    "with_buffer


    METHOD contains.
      DATA ls_sbuspart TYPE sbuspart.
      DATA lv_idx TYPE sytabix.
      DATA lx_error TYPE REF TO cx_static_check.
      DATA lo_buffer TYPE REF TO lcl_table_buffer.
      TRY.
          ls_sbuspart-buspartnum = '00002075'.
          lo_buffer = lcl_table_buffer=>factory(
            iv_text = c_text_save
            iv_value = ls_sbuspart
            iv_key = 'BUSPARTNUM' ).
          lo_buffer->put( ls_sbuspart ).
          lv_idx = lo_buffer->contains( ls_sbuspart ).
          cl_abap_unit_assert=>assert_equals(
            exp = 1
            act = lv_idx
            msg = 'LCL_TABLE_BUFFER->CONTAINS Error' ).
        CATCH lcx_buffer_error INTO lx_error.
          cl_aunit_assert=>fail( msg = | CONTAINS { lx_error->get_text( ) } |  ).
      ENDTRY.
    ENDMETHOD.


    METHOD save_buffer.
      DATA ls_sbuspart TYPE sbuspart.
      DATA ls_sbook TYPE sbook.
      DATA lx_error TYPE REF TO cx_static_check.
      DATA lo_first TYPE REF TO lcl_table_buffer.
      DATA lo_next TYPE REF TO lcl_table_buffer.
      TRY.
          lo_first = lcl_table_buffer=>factory(
            iv_text = c_text_save
            iv_value = ls_sbuspart
            iv_key = 'BUSPARTNUM' ).
          lo_next = lcl_table_buffer=>factory(
            iv_text = c_text_save
            iv_value = ls_sbuspart
            iv_key = 'BUSPARTNUM' ).
          cl_abap_unit_assert=>assert_equals(
            exp = lo_first
            act = lo_next
            msg = |LCL_TABLE_BUFFER=>FACTORY Cache Error: { c_text_save } | ).
        CATCH lcx_buffer_error INTO lx_error.
          cl_aunit_assert=>fail( msg = | SAVE_BUFFER { lx_error->get_text( ) } |  ).
      ENDTRY.
    ENDMETHOD.
  ENDCLASS.                    "lcl_test IMPLEMENTATION




  ENDCLASS.                    "lcl_test IMPLEMENTATION

 

An ABAP implementation of an associative array (aka symbol table or map)

Error rendering macro 'code': Invalid value specified for parameter 'com.atlassian.confluence.ext.code.render.InvalidValueException'
*----------------------------------------------------------------------*
REPORT zz_buffer.


*----------------------------------------------------------------------*
*       CLASS lcx_buffer_error DEFINITION
*----------------------------------------------------------------------*
CLASS lcx_buffer_error DEFINITION INHERITING FROM cx_static_check.
ENDCLASS.                    "lcx_buffer_error DEFINITION
*----------------------------------------------------------------------*
*       CLASS lcx_buffer_key_in_buffer DEFINITION
*----------------------------------------------------------------------*
CLASS lcx_buffer_key_in_buffer DEFINITION INHERITING FROM lcx_buffer_error.
ENDCLASS.                    "lcx_buffer_key_in_buffer DEFINITION
*----------------------------------------------------------------------*
*       CLASS lcx_buffer_value_not_found DEFINITION
*----------------------------------------------------------------------*
CLASS lcx_buffer_value_not_found DEFINITION INHERITING FROM lcx_buffer_error.
ENDCLASS.                    "lcx_buffer_value_not_found DEFINITION


*----------------------------------------------------------------------*
*       INTERFACE lif_entry DEFINITION
*----------------------------------------------------------------------*
INTERFACE lif_entry.
  METHODS find
    IMPORTING iv_key TYPE any
    RETURNING value(rv_found) TYPE flag.
  METHODS get
    EXPORTING value(ev_value) TYPE any.
ENDINTERFACE.                    "lif_entry DEFINITION


*----------------------------------------------------------------------*
*       CLASS lcl_entry DEFINITION
*----------------------------------------------------------------------*
CLASS lcl_entry DEFINITION CREATE PRIVATE.
  PUBLIC SECTION.
    INTERFACES lif_entry.

    CLASS-METHODS factory
      IMPORTING iv_key TYPE any
                iv_value TYPE any
      RETURNING value(ri_entry) TYPE REF TO lif_entry.


  PROTECTED SECTION.
    DATA mr_key   TYPE REF TO data.
    DATA mr_value TYPE REF TO data.
    METHODS constructor
      IMPORTING iv_key TYPE any
                iv_value TYPE any.
ENDCLASS.                    "lcl_entry DEFINITION


*----------------------------------------------------------------------*
*       CLASS lcl_entry IMPLEMENTATION
*----------------------------------------------------------------------*
CLASS lcl_entry IMPLEMENTATION.


  METHOD constructor.
    FIELD-SYMBOLS <lv_ref> TYPE any.
    super->constructor( ).
    CREATE DATA mr_key LIKE iv_key.
    ASSIGN mr_key->* TO <lv_ref>.
    <lv_ref> = iv_key.
    CREATE DATA mr_value LIKE iv_value.
    ASSIGN mr_value->* TO <lv_ref>.
    <lv_ref> = iv_value.
  ENDMETHOD.                    "constructor


  METHOD factory.
    CREATE OBJECT ri_entry TYPE lcl_entry
      EXPORTING
        iv_key   = iv_key
        iv_value = iv_value.
  ENDMETHOD.                    "factory


  METHOD lif_entry~find.
    FIELD-SYMBOLS <lv_ref> TYPE any.
    CLEAR rv_found.
    ASSIGN mr_key->* TO <lv_ref>.
    CHECK <lv_ref> EQ iv_key.
    rv_found = abap_true.
  ENDMETHOD.                    "lif_entry~find

  METHOD lif_entry~get.
    FIELD-SYMBOLS <lv_ref> TYPE any.
    ASSIGN mr_value->* TO <lv_ref>.
    ev_value = <lv_ref>.
  ENDMETHOD.                    "get
ENDCLASS.                    "lcl_entry IMPLEMENTATION


*----------------------------------------------------------------------*
*       CLASS lcl_map DEFINITION
*----------------------------------------------------------------------*
CLASS lcl_map DEFINITION CREATE PRIVATE.
  PUBLIC SECTION.
    METHODS insert
      IMPORTING iv_key TYPE any
                iv_value TYPE any
      RAISING lcx_buffer_key_in_buffer .


    METHODS get_size
      RETURNING value(rv_size) TYPE syindex.


    METHODS isempty
      RETURNING value(rv_empty) TYPE flag.


    METHODS contains
      IMPORTING iv_key TYPE any
      RETURNING value(rv_found) TYPE flag.


    METHODS remove
      IMPORTING iv_key TYPE any
      RETURNING value(rv_found) TYPE flag.


    METHODS lookup
      IMPORTING iv_key TYPE any
      EXPORTING ev_value TYPE any
      RAISING lcx_buffer_value_not_found.

    CLASS-METHODS factory
      IMPORTING iv_name TYPE csequence
      RETURNING value(ro_buffer) TYPE REF TO lcl_map
      RAISING lcx_buffer_error.
  PRIVATE SECTION.
    TYPES tt_buffer TYPE STANDARD TABLE OF REF TO lif_entry.

    DATA mt_buffer TYPE tt_buffer.
    DATA mv_name TYPE string.
ENDCLASS.                    "lcl_map DEFINITION

*----------------------------------------------------------------------*
*       CLASS lCL_MAP IMPLEMENTATION
*----------------------------------------------------------------------*
CLASS lcl_map IMPLEMENTATION.


  METHOD factory.
    CREATE OBJECT ro_buffer.
    ro_buffer->mv_name = iv_name.
  ENDMETHOD.                    "create


  METHOD get_size.
    rv_size = lines( mt_buffer ).
  ENDMETHOD.                    "get_size


  METHOD isempty.
    IF mt_buffer IS INITIAL.
      rv_empty = abap_true.
    ELSE.
      rv_empty = abap_false.
    ENDIF.
  ENDMETHOD.                    "isEmpty


  METHOD contains.
*   Search for already buffered value
    DATA li_entry TYPE REF TO lif_entry.
    CLEAR rv_found.
    LOOP AT mt_buffer INTO li_entry.
      CHECK li_entry->find( iv_key ) EQ abap_true.
      rv_found = abap_true.
      RETURN.
    ENDLOOP.
  ENDMETHOD.                    "contains


  METHOD lookup.
*   Search for already buffered value
    DATA li_entry TYPE REF TO lif_entry.
    LOOP AT mt_buffer INTO li_entry.
      CHECK li_entry->find( iv_key ) EQ abap_true.
      li_entry->get( IMPORTING ev_value = ev_value ).
      RETURN.
    ENDLOOP.
*   Value was not found
    RAISE EXCEPTION TYPE lcx_buffer_value_not_found.
  ENDMETHOD.                    "GET


  METHOD insert.
*   Search for already buffered value
    DATA li_entry TYPE REF TO lif_entry.
    IF me->contains( iv_key ) EQ abap_true.
*     key was already in the buffer
      RAISE EXCEPTION TYPE lcx_buffer_key_in_buffer.
    ENDIF.
*   Value was not found, insert:
    li_entry = lcl_entry=>factory( iv_key = iv_key
                                   iv_value = iv_value ).
    INSERT li_entry INTO TABLE mt_buffer.
  ENDMETHOD.                    "insert


  METHOD remove.
*   remove existing entry
    DATA li_entry TYPE REF TO lif_entry.
    CLEAR rv_found.
    LOOP AT mt_buffer INTO li_entry.
      CHECK li_entry->find( iv_key ) EQ abap_true.
      rv_found = abap_true.
      DELETE mt_buffer.
      FREE li_entry.
      RETURN.
    ENDLOOP.
  ENDMETHOD.                    

ENDCLASS.                    "lCL_BUFFER IMPLEMENTATION

*----------------------------------------------------------------------*
*       CLASS lcl_test DEFINITION
*----------------------------------------------------------------------*
CLASS lcl_test DEFINITION FOR TESTING
  DURATION MEDIUM RISK LEVEL HARMLESS.

  PRIVATE SECTION.
    CONSTANTS c_max_size TYPE i VALUE 1000.
    DATA mv_sbook_size TYPE i.
    DATA mv_buffer_size TYPE i.
    DATA mt_sbook TYPE STANDARD TABLE OF sbook.


    METHODS setup.
    METHODS without_buffer FOR TESTING.
    METHODS with_buffer FOR TESTING.
ENDCLASS.                    "lcl_test DEFINITION


*----------------------------------------------------------------------*
*       CLASS lcl_test IMPLEMENTATION
*----------------------------------------------------------------------*
CLASS lcl_test IMPLEMENTATION.

  METHOD setup.
    DATA lt_customid TYPE STANDARD TABLE OF sbook-customid.
    SELECT * FROM sbook INTO TABLE mt_sbook
      UP TO c_max_size ROWS.
*    SELECT COUNT( DISTINCT customid ) INTO mv_buffer_size
*      FROM sbook
*      UP TO c_max_size ROWS.
* Ooops! only one row was returned
*    Have to use the convoluted logic below
    SELECT customid FROM sbook
      INTO TABLE lt_customid
      FOR ALL ENTRIES IN mt_sbook
      WHERE carrid = mt_sbook-carrid
        AND connid = mt_sbook-connid
        AND fldate = mt_sbook-fldate
        AND bookid = mt_sbook-bookid.
      mv_buffer_size = lines( lt_customid ).
      mv_sbook_size = lines( mt_sbook ).
    ENDMETHOD.                    "query_sbook

    METHOD without_buffer.
      DATA ls_sbuspart TYPE sbuspart.
      DATA ls_sbook TYPE sbook.
      DATA lv_counter TYPE i.
      LOOP AT mt_sbook INTO ls_sbook.
        SELECT SINGLE * FROM sbuspart INTO ls_sbuspart
          WHERE buspartnum = ls_sbook-customid.
        ADD 1 TO lv_counter.
      ENDLOOP.
      cl_aunit_assert=>assert_equals( exp = mv_sbook_size
                                      act = lv_counter
                                      msg = 'WITHOUT_BUFFER error' ).
    ENDMETHOD.                    "without_buffer

    METHOD with_buffer.
      DATA lo_buffer TYPE REF TO lcl_map.
      DATA ls_sbuspart TYPE sbuspart.
      DATA ls_sbook TYPE sbook.
      DATA lx_error TYPE REF TO cx_static_check.
      DATA lv_counter TYPE i.
      DATA lv_text TYPE string.
      TRY.
          LOOP AT mt_sbook INTO ls_sbook.
            AT FIRST.
              lo_buffer = lcl_map=>factory( 'CUSTOMER_DETAILS' ).
            ENDAT.
            CHECK lo_buffer->contains( ls_sbook-customid ) EQ abap_false.
*         If we haven't saved it yet, get it and save it
            SELECT SINGLE * FROM sbuspart INTO ls_sbuspart
              WHERE buspartnum = ls_sbook-customid.
            lo_buffer->insert( iv_key   = ls_sbook-customid
                               iv_value = ls_sbuspart ).
          ENDLOOP.
          lv_counter = lo_buffer->get_size( ).
          cl_aunit_assert=>assert_equals( exp = mv_buffer_size
                                          act = lv_counter
                                          msg = 'WITH_BUFFER error' ).
        CATCH lcx_buffer_error INTO lx_error.
          lv_text = | WITH_BUFFER { lx_error->get_text( ) } |.
          cl_aunit_assert=>fail( msg = lv_text ).
      ENDTRY.
    ENDMETHOD.                    "with_buffer
  ENDCLASS.                    "lcl_test IMPLEMENTATION
REPORT  zceil_floor .
*-----------------------------------------------------------------------------------*
*              selection screen parameters
*----------------------------------------------------------------------------------*
PARAMETERS: p_int  TYPE i ,
            p_int1 TYPE i .
*-----------------------------------------------------------------------------------*
*              data declarations
*----------------------------------------------------------------------------------*
DATA: value  TYPE p DECIMALS 2  ,
      value1  TYPE p DECIMALS 2 ,
      value2  TYPE p DECIMALS 2 .
*-----------------------------------------------------------------------------------*
*              start of selection
*----------------------------------------------------------------------------------*
START-OF-SELECTION.
  value = p_int / p_int1 .
  value1 = ceil( value  ) .
  value2 = floor( value ) .
*----display output
  WRITE:/ 'the actual value is  :           ' ,   value .
  WRITE:/ 'value using the ceil  function : ' , value1 .
  WRITE:/ 'value using the floor function : ' , value2 .
 

Horst Keller's Blog - ABAP news for release 740 SP05

100 lines of test code with a Unit Test that fails.

Error rendering macro 'code': Invalid value specified for parameter 'com.atlassian.confluence.ext.code.render.InvalidValueException'
REPORT YY_CORRESPONDING.
TYPES ts_sat TYPE if_atra_uml_tool=>ty_sat_record.
TYPES:  BEGIN OF ts_call,
          prog TYPE program,
          type TYPE trobjtype,
          inst TYPE satr_de_instance,
          lcl  TYPE program,
          mod  TYPE seocpdname,
        END OF ts_call.
TYPES:
  BEGIN OF ts_trace,
    id        TYPE satr_de_id,
    aus_ebene TYPE satr_de_ebene,
    caller    TYPE ts_call,
    called    TYPE ts_call,
  END OF ts_trace.
INTERFACE lif_unit_test.
ENDINTERFACE.
CLASS lcl_converter DEFINITION FRIENDS lif_unit_test.
  PUBLIC SECTION.
  PRIVATE SECTION.
    METHODS copy_fields
      IMPORTING is_trace      TYPE ts_sat
      RETURNING VALUE(rs_sat) TYPE ts_trace.
    METHODS operator
      IMPORTING is_trace      TYPE ts_sat
      RETURNING VALUE(rs_sat) TYPE ts_trace.
ENDCLASS.
CLASS ltc_converter DEFINITION
  INHERITING FROM cl_aunit_assert FOR TESTING
  RISK LEVEL HARMLESS DURATION SHORT.
  PUBLIC SECTION.
    INTERFACES lif_unit_test.
  PRIVATE SECTION.
    DATA ms_sat TYPE ts_sat.
    DATA mo_convert TYPE REF TO lcl_converter.
    METHODS setup.
    METHODS convert FOR TESTING.
ENDCLASS.
CLASS lcl_converter IMPLEMENTATION.
  METHOD copy_fields.
    MOVE-CORRESPONDING is_trace TO rs_sat.
    rs_sat-caller = VALUE #( prog = is_trace-caller
                             type = is_trace-caller_type
                             inst = is_trace-caller_inst
                             lcl = is_trace-caller_lcl
                             mod = is_trace-caller_mod ).
    rs_sat-called = VALUE #( prog = is_trace-called
                             type = is_trace-called_type
                             inst = is_trace-called_inst
                             lcl = is_trace-called_lcl
                             mod = is_trace-called_mod ).
  ENDMETHOD.
  METHOD operator.
    rs_sat =  CORRESPONDING #( is_trace MAPPING
            ( caller = table_line MAPPING prog = caller
                                          type = caller_type
                                          inst = caller_inst
                                          lcl = caller_lcl
                                          mod = caller_mod  )
            ( called = table_line MAPPING prog = called
                                          type = called_type
                                          inst = called_inst
                                          lcl = called_lcl
                                          mod = called_mod  )   ).
  ENDMETHOD.
ENDCLASS.
CLASS ltc_converter IMPLEMENTATION.
  METHOD setup.
    mo_convert = NEW #( ).
    ms_sat = VALUE #( id = 'm'
                      caller = 'PROGRAM'
                      caller_mod = 'TEST'
                      called_type = 'CLAS'
                      called_inst = 4
                      called_lcl = 'LCL_DEMO' ).
  ENDMETHOD.
  METHOD convert.
    DATA(ls_trace) = mo_convert->copy_fields( ms_sat ).
    DATA(ls_act) = mo_convert->operator( ms_sat ).
    assert_equals(  act = ls_act
                    exp = ls_trace
                    msg = 'CONVERSION Error').
  ENDMETHOD.
ENDCLASS.


List of all pages

Pages at first level

Author: Jacques Nomssi
Submitted: 2014-01-21
Related Links:

Description Code:

Error rendering macro 'code': Invalid value specified for parameter 'com.atlassian.confluence.ext.code.render.InvalidValueException'
REPORT ysdnblog_jnn.
DATA: BEGIN OF gs_sel,
        matnr TYPE matnr,
        mtart TYPE mtart,
        matkl TYPE matkl,
      END OF gs_sel.
SELECTION-SCREEN BEGIN OF SCREEN 200.
SELECT-OPTIONS:
  so_matnr FOR gs_sel-matnr,
  so_mtart FOR gs_sel-mtart,
  so_matkl FOR gs_sel-matkl.
PARAMETERS p_rows TYPE count DEFAULT '100'.
SELECTION-SCREEN END OF SCREEN 200.
INTERFACE lif_unit_test.
ENDINTERFACE.
CLASS lcl_param DEFINITION FRIENDS lif_unit_test.
  PUBLIC SECTION.
    TYPES:
      tt_matnr_range TYPE RANGE OF matnr,
      tt_mtart_range TYPE RANGE OF mtart,
      tt_matkl_range TYPE RANGE OF matkl.
    CLASS-METHODS factory
      RETURNING value(ro_param) TYPE REF TO lcl_param.
    DATA mv_rows TYPE count READ-ONLY.
    DATA mt_matnr_range TYPE tt_matnr_range READ-ONLY.
    DATA mt_mtart_range TYPE tt_mtart_range READ-ONLY.
    DATA mt_matkl_range TYPE tt_matkl_range READ-ONLY.
  PRIVATE SECTION.
    METHODS get_selection.
ENDCLASS.                    "lcl_param DEFINITION
INTERFACE lif_data_source.
  METHODS get RETURNING value(rr_data) TYPE REF TO data.
ENDINTERFACE.                    "lif_data_source DEFINITION
CLASS lcl_mara DEFINITION FRIENDS lif_unit_test.
  PUBLIC SECTION.
    INTERFACES lif_data_source.
    ALIASES get FOR lif_data_source~get.
    CLASS-METHODS factory
      IMPORTING io_param TYPE REF TO lcl_param
      RETURNING value(ro_mara) TYPE REF TO lcl_mara.
  PRIVATE SECTION.
    METHODS query
      IMPORTING io_param TYPE REF TO lcl_param.
    DATA mt_mara TYPE mara_tt.
ENDCLASS.                    "lcl_mara DEFINITION
CLASS lcl_view DEFINITION CREATE PRIVATE FRIENDS lif_unit_test.
  PUBLIC SECTION.
    CLASS-METHODS factory
      IMPORTING ii_source TYPE REF TO lif_data_source
      RETURNING value(ro_view) TYPE REF TO lcl_view
      RAISING cx_salv_msg.
    METHODS display.
  PRIVATE SECTION.
    METHODS alv_init
      CHANGING ct_data TYPE STANDARD TABLE
      RAISING cx_salv_msg.
    DATA mo_alv TYPE REF TO cl_salv_table.
ENDCLASS.                    "lcl_view DEFINITION
CLASS lcl_ctrl DEFINITION FRIENDS lif_unit_test.
  PUBLIC SECTION.
    CLASS-METHODS main.
  PRIVATE SECTION.
    CLASS-METHODS create_view
      RETURNING value(ro_view) TYPE REF TO lcl_view
      RAISING cx_salv_msg.
ENDCLASS.
CLASS lcl_ctrl IMPLEMENTATION.
  METHOD create_view.
    DATA lo_param TYPE REF TO lcl_param.
    DATA lo_mara TYPE REF TO lcl_mara.
    CALL SELECTION-SCREEN 200.
    lo_param = lcl_param=>factory( ).
    lo_mara = lcl_mara=>factory( lo_param ).
    ro_view = lcl_view=>factory( lo_mara ).
  ENDMETHOD.                    "create_view
  METHOD main.
    DATA lo_view TYPE REF TO lcl_view.
    DATA lx_error TYPE REF TO cx_static_check.
    TRY.
        lo_view = create_view( ).
        lo_view->display( ).
      CATCH cx_static_check INTO lx_error.
        MESSAGE lx_error TYPE 'E' DISPLAY LIKE 'I'.
    ENDTRY.
  ENDMETHOD.
ENDCLASS.
START-OF-SELECTION.
  lcl_ctrl=>main( ).

CLASS lcl_param IMPLEMENTATION.
  METHOD factory.
    CREATE OBJECT ro_param.
    ro_param->get_selection( ).
  ENDMETHOD.                    "factory
  METHOD get_selection.
    mv_rows = p_rows.
    mt_matnr_range[] = so_matnr[].
    mt_matkl_range[] = so_matkl[].
    mt_mtart_range[] = so_mtart[].
  ENDMETHOD.                    "get_selection
ENDCLASS.                    "lcl_param IMPLEMENTATION
CLASS lcl_mara IMPLEMENTATION.
  METHOD factory.
    CREATE OBJECT ro_mara.
    ro_mara->query( io_param ).
  ENDMETHOD.                    "factory
  METHOD query.
    CLEAR mt_mara[].
    SELECT * FROM mara
      INTO CORRESPONDING FIELDS OF TABLE mt_mara
      UP TO io_param->mv_rows ROWS
      WHERE matnr IN io_param->mt_matnr_range
        AND mtart IN io_param->mt_mtart_range
        AND matkl IN io_param->mt_matkl_range.
  ENDMETHOD.                    "query
  METHOD get.
    GET REFERENCE OF mt_mara INTO rr_data.
  ENDMETHOD.                    "get_ref
ENDCLASS.                    "lcl_mara IMPLEMENTATION
CLASS lcl_view IMPLEMENTATION.
  METHOD factory.
    FIELD-SYMBOLS <lt_table> TYPE STANDARD TABLE.
    DATA lr_data TYPE REF TO data.
    CREATE OBJECT ro_view.
    lr_data = ii_source->get( ).
    ASSIGN lr_data->* TO <lt_table>.
    ro_view->alv_init( CHANGING ct_data = <lt_table> ).
  ENDMETHOD.                    "factory
  METHOD display.
    mo_alv->display( ).
  ENDMETHOD.                    "display
  METHOD alv_init.
    DATA lo_functions TYPE REF TO cl_salv_functions.
    cl_salv_table=>factory(
      IMPORTING r_salv_table   = mo_alv
      CHANGING  t_table        = ct_data ).
    lo_functions = mo_alv->get_functions( ).
    lo_functions->set_all( abap_true ).
  ENDMETHOD.                    "alv_init
ENDCLASS.                    "lcl_view IMPLEMENTATION

Author: Marcelo Ramos
Submitted: 09/22/2008

Related Links:

Class Definition

Error rendering macro 'code': Invalid value specified for parameter 'com.atlassian.confluence.ext.code.render.InvalidValueException'
*---------------------------------------------------------------------*
*       CLASS main DEFINITION
*---------------------------------------------------------------------*
CLASS main DEFINITION.

  PUBLIC SECTION.

    "// Instance Methods ( Note we use the statement 'METHODS'
    "// to define an instance method )
    METHODS set_data IMPORTING i_data TYPE string.
    METHODS get_data RETURNING value(r_data) TYPE string.
    METHODS print_attribute IMPORTING i_data TYPE string.

    "// Instance Methods ( Note we use the statement 'CLASS-METHODS'
    "// to define a static method )
    CLASS-METHODS set_classdata IMPORTING i_data TYPE string.
    CLASS-METHODS get_classdata RETURNING value(r_data) TYPE string.
    CLASS-METHODS print_classattribute IMPORTING i_data TYPE string.

  PROTECTED SECTION.

    "// Instance Attribute ( Note we use the statement 'DATA'
    "// to define an instance attribute )
    DATA attribute TYPE string.
    "// Static Attribute ( Note we use the statement 'CLASS-DATA'
    "// to define a static attribute )
    CLASS-DATA classattribute TYPE string.

  PRIVATE SECTION.

    "// Instace event ( Note we use the statement 'EVENTS'
    "// to define aN instance event )
    EVENTS event EXPORTING value(e_data) TYPE string.

    "// Instace event ( Note we use the statement 'CLASS-EVENTS'
    "// to define a static event )
    CLASS-EVENTS classevent EXPORTING value(e_data) TYPE string.

    "// For more informations about events see the following example:
    "// ABAP Objects - Creating your First Local Class - Using Events

ENDCLASS.                    "main DEFINITION

Class Implementation

Error rendering macro 'code': Invalid value specified for parameter 'com.atlassian.confluence.ext.code.render.InvalidValueException'
*---------------------------------------------------------------------*
*       CLASS main IMPLEMENTATION
*---------------------------------------------------------------------*
CLASS main IMPLEMENTATION.

  METHOD set_data.

    CONCATENATE 'Instance Attribute value' i_data
                               INTO attribute SEPARATED BY space.

  ENDMETHOD.                    "set_data

  METHOD get_data.

    MOVE attribute TO r_data.

  ENDMETHOD.                    "get_data

  METHOD set_classdata.

    CONCATENATE 'Static Attribute value' i_data
                               INTO classattribute SEPARATED BY space.

  ENDMETHOD.                    "set_classdata

  METHOD get_classdata.

    MOVE main=>classattribute TO r_data.

  ENDMETHOD.                    "get_classdata

  METHOD print_attribute.

    WRITE: i_data, /.

  ENDMETHOD.                    "print_attribute

  METHOD print_classattribute.

    WRITE: i_data, /.

  ENDMETHOD.                    "print_classattribute

ENDCLASS.                    "main IMPLEMENTATION

Data Definition

Error rendering macro 'code': Invalid value specified for parameter 'com.atlassian.confluence.ext.code.render.InvalidValueException'
DATA: var type char20.

Calling Static Methods

Error rendering macro 'code': Invalid value specified for parameter 'com.atlassian.confluence.ext.code.render.InvalidValueException'
START-OF-SELECTION.

  "// Calling a Static method (note we don't have a object )
  "// instead we use the <class name>=><method name>.
  main=>set_classdata( 'SDN' ).
  var = main=>get_classdata( ).
  "// Print the var value
  main=>print_classattribute( var ).

Object Definition

Error rendering macro 'code': Invalid value specified for parameter 'com.atlassian.confluence.ext.code.render.InvalidValueException'
DATA: object_reference TYPE REF TO main.

Instance Creation

Error rendering macro 'code': Invalid value specified for parameter 'com.atlassian.confluence.ext.code.render.InvalidValueException'
  CREATE OBJECT object_reference.

Calling Instance Methods

Error rendering macro 'code': Invalid value specified for parameter 'com.atlassian.confluence.ext.code.render.InvalidValueException'
  "// - Calling a Instance Method( Note we have to use a object to
  "// access the insntace components of class main )
  "// - Note we're using the statment "CALL METHOD", see looking for
  "// functional & General methods for more informations
  CALL METHOD object_reference->set_data( 'BPX' ).
  var = object_reference->get_data(  ).
  object_reference->print_attribute( var ).

The result is

Error rendering macro 'code': Invalid value specified for parameter 'com.atlassian.confluence.ext.code.render.InvalidValueException'
"Static Attribute value SDN
"Instance Attribute value BPX
Error rendering macro 'code': Invalid value specified for parameter 'com.atlassian.confluence.ext.code.render.InvalidValueException'
REPORT ysubdel1 LINE-SIZE 120.
TYPES : BEGIN OF typ_tab ,
 name(15) TYPE c ,
 age TYPE i ,
END OF typ_tab .
DATA : num1 TYPE i VALUE 5 .
*----------------------------------------------------------------------*
*       CLASS c1 DEFINITION
*----------------------------------------------------------------------*
CLASS c1 DEFINITION .
  PUBLIC SECTION.
    METHODS : meth1 .
    DATA : l_num LIKE num1 ,
    it_tab TYPE STANDARD TABLE OF typ_tab ,
    w_tab LIKE LINE OF it_tab.
ENDCLASS.                    "c1 DEFINITION
*----------------------------------------------------------------------*
*       CLASS c1 IMPLEMENTATION
*----------------------------------------------------------------------*
CLASS c1 IMPLEMENTATION.
  METHOD : meth1 .
    DATA : l_cnum(2) TYPE c.
    l_num = 0.
    DO 5 TIMES.
      l_num = l_num + 1.
      l_cnum = l_num.
      CONCATENATE 'Student-'
      l_cnum
      INTO w_tab-name.
      w_tab-age = num1 * l_num .
      APPEND w_tab TO it_tab.
      CLEAR w_tab.
    ENDDO.
    LOOP AT it_tab INTO w_tab.
      WRITE:/5 w_tab-name ,
      w_tab-age.
    ENDLOOP.
  ENDMETHOD.                    ":
ENDCLASS.                    "c1 IMPLEMENTATION

START-OF-SELECTION.
  DATA : obj1 TYPE REF TO c1.
  CREATE OBJECT : obj1.

  CALL METHOD obj1->meth1.


Output 
 Student-1                5   
 Student-2               10   
 Student-3               15   
 Student-4               20   
 Student-5               25  

Error rendering macro 'code': Invalid value specified for parameter 'com.atlassian.confluence.ext.code.render.InvalidValueException'
REPORT yoopstests.
*----------------------------------------------------------------------*
*       CLASS class1 DEFINITION
*----------------------------------------------------------------------*
CLASS class1 DEFINITION.
  PUBLIC SECTION.
    METHODS : method1 .
ENDCLASS.                    "class1 DEFINITION
*----------------------------------------------------------------------*
*       CLASS class2 DEFINITION
*----------------------------------------------------------------------*
CLASS class2 DEFINITION.
  PUBLIC SECTION.
    METHODS : method2 .
ENDCLASS.                    "class2 DEFINITION
*----------------------------------------------------------------------*
*       CLASS class1 IMPLEMENTATION
*----------------------------------------------------------------------*
CLASS class1 IMPLEMENTATION.
  METHOD :method1.
    DATA : i_num TYPE i VALUE 2.
    WRITE:/5 i_num.
  ENDMETHOD.                    ":method1
ENDCLASS.                    "class1 IMPLEMENTATION
*----------------------------------------------------------------------*
*       CLASS class2 IMPLEMENTATION
*----------------------------------------------------------------------*
CLASS class2 IMPLEMENTATION.
  METHOD : method2.
    DATA : obj1 TYPE REF TO class1.
    CREATE OBJECT obj1.
    CALL METHOD obj1->method1.
  ENDMETHOD.                    ":
ENDCLASS.                    "class2 IMPLEMENTATION

START-OF-SELECTION.
  DATA : my_obj TYPE REF TO class2.
  CREATE OBJECT : my_obj.
  CALL METHOD my_obj->method2.

Types of Classes:

 
CLASS myclass DEFINITION

PUBLIC SECTION.

........................................

PRIVATE SECTION.

........................................

PROTECTED SECTION

........................................

ENDCLASS

Attributes

The syntax for the declaration of an instance attribute attr is:

CLASS-DATA

DATA attr TYPE dtype [READ-ONLY].

The syntax for the declaration of a static attribute attr is:

CLASS-DATA attr TYPE dtype [READ-ONLY].

Declaration of the Attribute of a Class

CLASS static.vehicle DEFINITION.

PUBLIC SECTION.

....................................

PRIVATE SECTION.

CLASS-DATA speed TYPE I.

ENDCLASS.

The syntax for the declaration of a constant attr is:

CONSTANTS attr TYPE dtype VALUE val.

Correspondingly, the syntax for the declaration of a static method
meth is:
CLASS-METHODS meth
.............................................

 

Declaration and Implementation of Methods :

CLASS static_vehicle DEFINITION.

PUBLIC SECTION.

CLASS-METHODS: accelerate IMPORTING delta TYPE i.

PRIVATE SECTION.

CLASS OATA speed TYPE i.

ENDCLASS.

CLASS static_vehicle IMPLEMENTATION.

METHOD accelerate.

speed = speed + delta.

ENDMETHOD.

METHOD show_speed.

DATA output TYPE string,

output = speed.

MESSAGE Output TYPE 'I'.

ENDMETHOD.

ENDCLASS.

Using a Local Class , Using Static Components

REPORT z_drive_local_static_vehicle.

CLASS static_vehicle DEFINITION.

...........................

ENDCLASS.

CLASS static_vehicle IMPLEMENTATION.

...........................

ENDCLASS.

START-OF-SELECTION.

static_vehicle => accelerate( 100 ).

static_vehicle => accelerate( 200 ).

static_vehicle => show_speed( ).

Class as a Template for Objects

REPORT z_vehicle

CLASS vehicle DEFINITION.

PUBLIC SECTION.

CLASS-METHODS: accelerate IMPORTING delta TYPE i.

PRIVATE SECTION.

DATA speed TYPE i.

ENDCLASS.

CLASS vehicle IMPLEMENTATION.

METHOD accelerate.

speed = speed + delta.

ENDMETHOD.

METHOD show_speed.

DATA output TYPE string,

output = speed.

MESSAGE Output TYPE 'I'.

ENDMETHOD.

ENDCLASS.

Creating and Referencing Objects

REPORT z_drive_veh1cles.

CLASS demo DEFINITION.

PUBLIC SECTION.

CLASS-METHODS main.

ENDCLASS.

CLASS demo IMPLEMENTATION.

METHOO main.

DATA: vehicle1 TYPE REF TO zcl_vehicle.

vehicle2 TYPE REF TO zcl_vehicle.

CREATE OBJECT: vehiclel.

   vehicle2.

vehicle1->accelerate( 100 ). Vehicle1->show_speed( ).

vehicle2->accelerate( 200 ). vehicle2->show_speed( ).

ENDMETHOD.

ENDCLASS.

START-OF-SELECTION.

 
demo->main( ).

 

A Quick Recap on Inheritance

As you all probably know Inheritance in ABAP Objects is the ability to take an existing class and create a new class in relation to it. The new class (referred to as a subclass) will inherit all common state and behavior from the existing class (referred to as the super class).

Within the subclass further specializations can be implemented. These specializations could be in the form of new methods and attributes. You could also redefine inherited methods and add custom logic specifically for use within the subclass.

When an object is instantiated, it is done so with reference to a specific type. For instance it could be typed to a class. We can access the object via any reference typed to the class the object was instantiated with.

Inheritance Polymorphism

Inheritance polymorphism allows us to make reference to that object via any variable that is typed to any super class of the class that the object was instantiated with.

The downside of referencing an object via it's superclass is you lose the ability to access certain specializations, as they can only be accessed via reference to the subclass.

The upside however is that you can still call methods that are available in the super class. If you have redefined the method in any subclass in the inheritance hierarchy. The ABAP runtime can determine the lowest possible implementation and will execute this. The ABAP runtime will only look up to the class that the object was originally instantiated with.

Conclusion

Now all of a sudden that tradeoff is looking pretty enticing. We can build complex logic with very detailed specializations and encapsulate the implementation under relevant components. If we need to add new functionality, it would be straightforward to create a new subclass and implement new specializations to handle our requirement. Then we are ready to use these in our applications.

This is a really powerful technique and if understood and applied correctly can reap massive rewards in the development of your applications.

Demo Bicycle Inheritance Polymorphism

The example below is quite detailed, but also contains many comments to supplement my thought processes here.

In a nutshell, I have created an inheritance hierarchy for different types of bicycles. They all share a common method ("get_status") that all subclasses of bicycle inherit and has been redefined. In the main program I add a reference to each object to a list typed to their super class "Bicycle". I then loop through the list and reference the common method. As you can see from the results the method implementation that is actually executed is dependent on the class that the object was instantiated with.

You can copy the below report and include programs into your system to check out how this works....

Error rendering macro 'code': Invalid value specified for parameter 'com.atlassian.confluence.ext.code.render.InvalidValueException'
*&---------------------------------------------------------------------*
*& Report  ZZZ_DEMO_POLYMORPHISM
*&
*&---------------------------------------------------------------------*
*& This program demonstrates examples of encapsulation, inheritance and polymorphism
*&---------------------------------------------------------------------*

REPORT  zzz_demo_polymorphism.

INCLUDE zzz_demo_gears_lib.
INCLUDE zzz_demo_passenger_lib.
INCLUDE zzz_demo_vehicle_lib.


*----------------------------------------------------------------------*
*       CLASS bicycle_demo DEFINITION
*----------------------------------------------------------------------*
* A class to execute the bicycle demo functionality
* This class is set as abstract as I do not want anyone extending
* the class or creating an instance of it as it makes no sense.
* It is only used to kick off the processing for this program
*----------------------------------------------------------------------*
CLASS bicycle_demo DEFINITION ABSTRACT FINAL.
  PUBLIC SECTION.
    CLASS-METHODS: run_demo.
ENDCLASS.                    "bicycle_demo DEFINITION

*----------------------------------------------------------------------*
*       CLASS bicycle_demo IMPLEMENTATION
*----------------------------------------------------------------------*
* In this demo we showcase the power of polymorphism via inheritance.
* As mentioned earlier we stated that objects can be referenced as
* objects of one of their super classes.  So a mountain bike could be
* referenced as a bicycle or as a vehicle.  By referencing an object
* via one of its super class means that you can only execute the methods
* defined in that super class.  However if that method is redefined in the
* subclass, then the ABAP Runtime will determine the lowest implementation
* of that method in the class hierarchy and execute that for the object
*----------------------------------------------------------------------*
CLASS bicycle_demo IMPLEMENTATION.
  METHOD run_demo.

    " Create a structured type of class bicycle
    " and also a table type based on the structured type
    TYPES: BEGIN OF lty_bike,
             bike TYPE REF TO bicycle,
           END OF lty_bike,
           ltty_bikes TYPE STANDARD TABLE OF lty_bike.

    DATA: l_bike TYPE lty_bike,
          lt_bikes TYPE ltty_bikes,
          lo_mountain_bike TYPE REF TO mountain_bike,
          lo_road_bike TYPE REF TO road_bike,
          lo_gear_system TYPE REF TO gear_system,
          lo_passenger TYPE REF TO passenger,
          lo_passenger_list TYPE REF TO passenger_list,
          l_status TYPE string.

    " Always better to use field symbols for looping
    " much better performance
    FIELD-SYMBOLS: <fs_bicycle> TYPE lty_bike.

    " Create a new instance of mountain bike and take it for a spin
    CREATE OBJECT lo_mountain_bike EXPORTING  e_max_passengers = 1
                                              e_max_gears = 10.
    " Get the reference to the passengers list for the mountain bike
    " and assign it to the passenger list field then add a new passenger
    lo_passenger_list = lo_mountain_bike->get_passengers_list( ).
    lo_passenger_list->add_passenger_by_name( e_first_name = 'Katan' e_last_name = 'Patel' ).
    " Get the reference to the gear system for the mountain bike
    " and assign it to the gear_system field
    lo_gear_system = lo_mountain_bike->get_gear_system( ).
    lo_mountain_bike->pedal_faster( 10 ).
    lo_gear_system->change_gear_up( ).
    lo_gear_system->change_gear_up( ).
    lo_mountain_bike->apply_brakes( 1 ).
    l_bike-bike = lo_mountain_bike.
    APPEND l_bike TO lt_bikes.
    FREE: lo_mountain_bike, lo_gear_system, lo_passenger_list.

    " Create another instance of mountain bike and take it for a spin
    CREATE OBJECT lo_mountain_bike EXPORTING e_max_passengers = 1
                                             e_max_gears = 18.
    " Get the reference to the passengers list for the mountain bike
    " and assign it to the passenger list field then add a new passenger
    lo_passenger_list = lo_mountain_bike->get_passengers_list( ).
    lo_passenger_list->add_passenger_by_name( e_first_name = 'Sherlock' e_last_name = 'Holmes' ).
    " Get the reference to the gear system for the mountain bike
    " and assign it to the gear_system field
    lo_gear_system = lo_mountain_bike->get_gear_system( ).
    lo_mountain_bike->pedal_faster( 20 ).
    lo_gear_system->change_gear_up( ).
    l_bike-bike = lo_mountain_bike.
    APPEND l_bike TO lt_bikes.
    FREE: lo_mountain_bike, lo_gear_system, lo_passenger_list.

    "Create a new instance of Road bike and take it for a spin
    CREATE OBJECT lo_road_bike EXPORTING e_max_passengers = 1
                                         e_max_gears = 20.
    " Get the reference to the passengers list for the mountain bike
    " and assign it to the passenger list field then add a new passenger
    lo_passenger_list = lo_road_bike->get_passengers_list( ).
    lo_passenger_list->add_passenger_by_name( e_first_name = 'James' e_last_name = 'Bond' ).
    " Get the reference to the gear system for the mountain bike
    " and assign it to the gear_system field
    lo_gear_system = lo_road_bike->get_gear_system( ).
    lo_road_bike->pedal_faster( 20 ).
    lo_gear_system->change_gear_up( ).
    lo_gear_system->change_gear_up( ).
    lo_gear_system->change_gear_up( ).
    lo_road_bike->apply_brakes( 5 ).
    l_bike-bike = lo_road_bike.
    APPEND l_bike TO lt_bikes.
    FREE: lo_road_bike, lo_gear_system, lo_passenger_list.

    " The impressive bit...
    " I can reference mountain bikes and Road Bikes as bicycles via the power of
    " inheritance.  Here I am looping through all my bicycles and executing output_status.
    " However if you run this, you will see different outputs are generated depending on the
    " type of bicycle being processed.  It it this ability that is polymorphism.
    " You can see that the ABAP runtime determines the correct method to execute by finding the
    " lowest possible implementation of the method "output_bicycle_status" for each of
    " the bicycle objects.  Setting these objects as bicycle does not mean that I cannot convert
    " them back later and use them as their respective objects. You will see in my later examples
    " how it is possible to convert them back
    LOOP AT lt_bikes ASSIGNING <fs_bicycle>.
      l_status = <fs_bicycle>-bike->get_status( ).
      WRITE:/ l_status.
    ENDLOOP.

  ENDMETHOD.                    "run_demo
ENDCLASS.                    "bicycle_demo IMPLEMENTATION


START-OF-SELECTION.
  " This is not required if you are not running a report
  " without using the classic list processing
  " Instead you could use an OO transaction
  " code instead.  It must call a static class method like
  " our 'run_demo' method
  bicycle_demo=>run_demo( ).
Error rendering macro 'code': Invalid value specified for parameter 'com.atlassian.confluence.ext.code.render.InvalidValueException'
*&---------------------------------------------------------------------*
*&  Include           ZZZ_DEMO_GEARS_LIB
*&---------------------------------------------------------------------*

*** Class Definitions ***
*----------------------------------------------------------------------*
*       CLASS gear_system DEFINITION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS gear_system DEFINITION.
  PUBLIC SECTION.
    TYPES: lty_gear(2) TYPE n.

    METHODS: constructor IMPORTING e_max_gears TYPE gear_system=>lty_gear,
             change_gear_up,
             change_gear_down,
             get_current_gear RETURNING value(e_current_gear) TYPE lty_gear.

  PRIVATE SECTION.
    DATA: l_current_gear TYPE lty_gear,
          l_max_gears TYPE lty_gear.
ENDCLASS.                    "gear_system DEFINITION

*** Class Implementations ***
*----------------------------------------------------------------------*
*       CLASS gear_system IMPLEMENTATION
*----------------------------------------------------------------------*
* Class defines a generic gear system for use in any object that uses
* gears
*----------------------------------------------------------------------*
CLASS gear_system IMPLEMENTATION.
  METHOD constructor.
    l_max_gears = e_max_gears.
  ENDMETHOD.                    "constructor
  METHOD change_gear_up.
    l_current_gear = l_current_gear + 1.
  ENDMETHOD.                    "change_gear_up
  METHOD change_gear_down.
    l_current_gear = l_current_gear - 1.
  ENDMETHOD.                    "change_gear_down
  METHOD get_current_gear.  "This is the only way to access this field of the class
    e_current_gear = l_current_gear.
  ENDMETHOD.                    "get_current_gear
ENDCLASS.                    "gear_system IMPLEMENTATION
Error rendering macro 'code': Invalid value specified for parameter 'com.atlassian.confluence.ext.code.render.InvalidValueException'
*&---------------------------------------------------------------------*
*&  Include           ZZZ_DEMO_PASSENGER_LIB
*&---------------------------------------------------------------------*


*----------------------------------------------------------------------*
*       CLASS passenger DEFINITION
*----------------------------------------------------------------------*
* A generic class for a passenger.
*----------------------------------------------------------------------*
CLASS passenger DEFINITION.
  PUBLIC SECTION.
    TYPES: lty_name TYPE string,
           lty_dest TYPE string.

    METHODS: constructor IMPORTING e_first_name TYPE lty_name
                                   e_last_name TYPE lty_name,
             set_first_name IMPORTING e_first_name TYPE lty_name,
             set_last_name IMPORTING e_last_name TYPE lty_name,
             get_full_name RETURNING value(i_full_name) TYPE lty_name,
             set_current_destination IMPORTING e_destination TYPE lty_dest,
             get_current_destination EXPORTING i_destination TYPE lty_dest.

  PRIVATE SECTION.
    DATA: l_first_name TYPE lty_name,
          l_last_name TYPE lty_name,
          l_current_destination TYPE lty_dest.
ENDCLASS.                    "passenger DEFINITION


*----------------------------------------------------------------------*
*       CLASS passenger_list DEFINITION
*----------------------------------------------------------------------*
*  A class to manage a list of passengers.  This should not be extended
* thus it is set as final.  It handles the management of all passengers
* I can use this in other objects and not worry about this when using
* instances of this class
*----------------------------------------------------------------------*
CLASS passenger_list DEFINITION FINAL.
  PUBLIC SECTION.
    TYPES: BEGIN OF lty_passengers,
             full_name TYPE passenger=>lty_name,
             passenger TYPE REF TO passenger,
           END OF lty_passengers,
           ltty_passengers TYPE SORTED TABLE OF lty_passengers
            WITH UNIQUE KEY full_name.

    METHODS: constructor IMPORTING e_max_passengers TYPE i,
             add_passenger IMPORTING e_passenger TYPE REF TO passenger
                           RETURNING value(i_added_successfully) TYPE REF TO cl_boolean,
             add_passenger_by_name IMPORTING e_first_name TYPE passenger=>lty_name
                                             e_last_name TYPE passenger=>lty_name
                           RETURNING value(i_added_successfully) TYPE REF TO cl_boolean,
             remove_passenger IMPORTING e_passenger TYPE REF TO passenger
                              RETURNING value(i_removed_successfully) TYPE REF TO cl_boolean,
             check_passenger_exists IMPORTING e_passenger TYPE REF TO passenger
                                    RETURNING value(i_does_exist) TYPE REF TO cl_boolean,
             set_max_passengers IMPORTING e_max_passengers TYPE i,
             get_max_passengers RETURNING VALUE(i_max_passengers) TYPE i,
             get_passengers RETURNING value(it_passengers) TYPE ltty_passengers,
             get_status RETURNING value(i_status) TYPE string.

  PRIVATE SECTION.
    DATA: lt_passengers TYPE ltty_passengers,
          l_max_passengers TYPE i.

ENDCLASS.                    "passenger_list DEFINITION

*----------------------------------------------------------------------*
*       CLASS passenger IMPLEMENTATION
*----------------------------------------------------------------------*
*  The implementation of the passenger
*----------------------------------------------------------------------*
CLASS passenger IMPLEMENTATION.
  METHOD constructor.
    l_first_name = e_first_name.
    l_last_name = e_last_name.
  ENDMETHOD.                    "constructor
  METHOD set_first_name.
    l_first_name = e_first_name.
  ENDMETHOD.                    "set_first_name
  METHOD set_last_name.
    l_last_name = e_last_name.
  ENDMETHOD.                    "set_last_name
  METHOD get_full_name.
    CONCATENATE l_first_name l_last_name INTO i_full_name
        SEPARATED BY space.
  ENDMETHOD.                    "get_full_name
  METHOD set_current_destination.
    l_current_destination = e_destination.
  ENDMETHOD.                    "set_current_destination
  METHOD get_current_destination.
    i_destination = l_current_destination.
  ENDMETHOD.                    "get_current_destination
ENDCLASS.                    "passenger IMPLEMENTATION

*----------------------------------------------------------------------*
*       CLASS passenger_list IMPLEMENTATION
*----------------------------------------------------------------------*
*  The implementation of class passenger_list
*----------------------------------------------------------------------*
CLASS passenger_list IMPLEMENTATION.
  METHOD constructor.
    l_max_passengers = e_max_passengers.
  ENDMETHOD.                    "constructor
  METHOD check_passenger_exists.
    DATA: l_full_name TYPE passenger=>lty_name.

    "Implicitly this should be false
    i_does_exist = cl_boolean=>false.

    " Get the passengers full name
    l_full_name = e_passenger->get_full_name( ).

    " Read the table to see if an entry already exists for the passenger
    READ TABLE lt_passengers
      WITH TABLE KEY full_name = l_full_name
      TRANSPORTING NO FIELDS.

    " If it does exist then set it to true
    IF sy-subrc = 0.
      i_does_exist = cl_boolean=>true.
    ENDIF.
  ENDMETHOD.                    "check_passenger_exists
  METHOD add_passenger.
    DATA: l_full_name TYPE passenger=>lty_name,
          l_passenger_record TYPE lty_passengers,
          l_no_records TYPE i.

    DESCRIBE TABLE lt_passengers LINES l_no_records.
    IF l_no_records = l_max_passengers.
      WRITE:/ 'Too many passengers on board.  No record added'.
      EXIT.
    ENDIF.

    "Implicitly this should be false
    i_added_successfully = cl_boolean=>false.

    "If the passenger does not already exist we can add it
    IF check_passenger_exists( e_passenger ) = cl_boolean=>false.
      l_passenger_record-full_name = e_passenger->get_full_name( ).
      l_passenger_record-passenger = e_passenger.
      INSERT l_passenger_record INTO TABLE lt_passengers .

      i_added_successfully = cl_boolean=>true.
    ELSE.
      WRITE:/ 'Passenger ', l_full_name, ' already exists'.
    ENDIF.
  ENDMETHOD.                    "add_passenger
  METHOD remove_passenger.
    DATA: l_full_name TYPE passenger=>lty_name.

    " Get the passengers full name
    l_full_name = e_passenger->get_full_name( ).

    "Implicitly this should be false
    i_removed_successfully = cl_boolean=>false.

    "If the passenger exists we can remove it
    IF check_passenger_exists( e_passenger ) = cl_boolean=>true.
      DELETE lt_passengers
        WHERE full_name = l_full_name.
      i_removed_successfully = cl_boolean=>true.
    ELSE.
      WRITE:/ 'Passenger ', l_full_name, ' does not exist'.
    ENDIF.
  ENDMETHOD.                    "remove_passenger
  METHOD set_max_passengers.
    l_max_passengers = e_max_passengers.
  ENDMETHOD.                    "set_max_passengers
  METHOD get_max_passengers.
    i_max_passengers = l_max_passengers.
  ENDMETHOD.                    "get_max_passengers
  METHOD add_passenger_by_name.
    "This method acts as a quick way to create passengers and add them
    " to my list
    DATA: lo_passenger TYPE REF TO passenger.

    CREATE OBJECT lo_passenger EXPORTING e_first_name = e_first_name
                                         e_last_name = e_last_name.
    add_passenger( lo_passenger ).
  ENDMETHOD.                    "add_passenger_by_name
  METHOD get_status.
    DATA: l_full_name TYPE passenger=>lty_name.

    FIELD-SYMBOLS: <fs_passenger> TYPE lty_passengers.

    i_status = 'My list of passengers includes: '.

    " Loop through all the passengers and return a string of passengers
    LOOP AT lt_passengers ASSIGNING <fs_passenger>.
      l_full_name = <fs_passenger>-passenger->get_full_name( ).
      IF sy-tabix = 1.
        CONCATENATE i_status l_full_name INTO i_status SEPARATED BY space.
      ELSE.
        CONCATENATE i_status ',' INTO i_status.
        CONCATENATE i_status l_full_name INTO i_status SEPARATED BY space.
      ENDIF.
    ENDLOOP.
    IF sy-subrc <> 0.
      i_status = 'I have no passengers'.
    ENDIF.
  ENDMETHOD.                    "get_status
  METHOD get_passengers.
    it_passengers = lt_passengers.
  ENDMETHOD.
ENDCLASS.                    "passenger_list IMPLEMENTATION
Error rendering macro 'code': Invalid value specified for parameter 'com.atlassian.confluence.ext.code.render.InvalidValueException'
*&---------------------------------------------------------------------*
*&  Include           ZZZ_DEMO_VEHICLE_LIB
*&---------------------------------------------------------------------*

*** Class Definitions ***
*----------------------------------------------------------------------*
*       CLASS vehicle DEFINITION
*----------------------------------------------------------------------*
* A generic implementation for vehicles
*----------------------------------------------------------------------*
CLASS vehicle DEFINITION.
  PUBLIC SECTION.
    TYPES: lty_speed(4) TYPE n.

    METHODS: constructor IMPORTING eo_max_passengers TYPE i,
             speed_up IMPORTING e_increment_speed TYPE lty_speed,
             slow_down IMPORTING e_decrement_speed TYPE lty_speed,
             get_current_speed RETURNING value(i_current_speed) TYPE lty_speed,
             get_passengers_list RETURNING value(io_passenger_list) TYPE REF TO passenger_list.

  PRIVATE SECTION.
    DATA: l_speed TYPE lty_speed,
          lo_passengers_list TYPE REF TO passenger_list.

ENDCLASS.                    "vehicle DEFINITION

*----------------------------------------------------------------------*
*       CLASS bicycle DEFINITION
*----------------------------------------------------------------------*
* A class for bicycles.  This is a sub class of vehicle
*----------------------------------------------------------------------*
CLASS bicycle DEFINITION INHERITING FROM vehicle.
  PUBLIC SECTION.
    METHODS: get_status RETURNING value(e_status) TYPE string,
             pedal_faster IMPORTING e_increment_speed TYPE vehicle=>lty_speed,
             apply_brakes IMPORTING e_decrement_speed TYPE vehicle=>lty_speed.
ENDCLASS.                    "bicycle DEFINITION

*----------------------------------------------------------------------*
*       CLASS mountain_bike DEFINITION
*----------------------------------------------------------------------*
* Mountain bikes have gears and so gear system is an attribute of
* mountain bike class.  This is a subclass of bicycle
*----------------------------------------------------------------------*
CLASS mountain_bike DEFINITION INHERITING FROM bicycle.

  PUBLIC SECTION.
    METHODS: constructor IMPORTING e_max_passengers TYPE i
                                   e_max_gears TYPE gear_system=>lty_gear,
             get_status REDEFINITION,
             get_gear_system RETURNING value(i_gear_system) TYPE REF TO gear_system.

  PRIVATE SECTION.
    DATA: l_gear_system TYPE REF TO gear_system.

ENDCLASS.                    "mountain_bike DEFINITION

*----------------------------------------------------------------------*
*       CLASS road_bike DEFINITION
*----------------------------------------------------------------------*
*   This is a subclass of bicycle
*----------------------------------------------------------------------*
CLASS road_bike DEFINITION INHERITING FROM bicycle.
  PUBLIC SECTION.
    METHODS: constructor IMPORTING e_max_passengers TYPE i
                          e_max_gears TYPE gear_system=>lty_gear,
             get_status REDEFINITION,
             get_gear_system RETURNING value(i_gear_system) TYPE REF TO gear_system.

  PRIVATE SECTION.
    DATA: l_gear_system TYPE REF TO gear_system.
ENDCLASS.                    "road_bike DEFINITION

*----------------------------------------------------------------------*
*       CLASS tandem_bike DEFINITION
*----------------------------------------------------------------------*
* This is a subclass of bicycle
*----------------------------------------------------------------------*
CLASS tandem_bike DEFINITION INHERITING FROM bicycle.
  PUBLIC SECTION.
    METHODS: constructor IMPORTING e_max_passengers TYPE i,
             get_status REDEFINITION.
ENDCLASS.                    "tandem_bike DEFINITION


*** Class Implementations ***
*----------------------------------------------------------------------*
*       CLASS vehicle IMPLEMENTATION
*----------------------------------------------------------------------*
* Superclass of all vehicles
*----------------------------------------------------------------------*
CLASS vehicle IMPLEMENTATION.
  METHOD constructor.
    CREATE OBJECT lo_passengers_list
        EXPORTING e_max_passengers = eo_max_passengers.
  ENDMETHOD.                    "constructor
  METHOD speed_up.
    l_speed = l_speed + e_increment_speed.
  ENDMETHOD.                    "speed_up
  METHOD slow_down.
    l_speed = l_speed - e_decrement_speed.

    "Speed cannot be less than 0
    IF l_speed LT 0.
      l_speed = 0.
    ENDIF.
  ENDMETHOD.                    "apply_breaks
  METHOD get_current_speed.
    i_current_speed = l_speed.
  ENDMETHOD.                    "get_current_speed
  METHOD get_passengers_list.
    io_passenger_list = lo_passengers_list.
  ENDMETHOD.                    "get_passengers_list
ENDCLASS.                    "vehicle IMPLEMENTATION


*----------------------------------------------------------------------*
*       CLASS bicycle IMPLEMENTATION
*----------------------------------------------------------------------*
* Superclass of all bicycles
*----------------------------------------------------------------------*
CLASS bicycle IMPLEMENTATION.
  METHOD get_status.
    DATA: l_output TYPE string,
          l_speed TYPE vehicle=>lty_speed.

    l_speed = get_current_speed( ).

    CONCATENATE 'I am a bicycle.  My speed is' l_speed
      INTO e_status SEPARATED BY space.
  ENDMETHOD.                    "output_bicycle_status
  METHOD apply_brakes.
    me->slow_down( e_decrement_speed ).
  ENDMETHOD.                    "apply_breaks
  METHOD pedal_faster.
    me->speed_up( e_increment_speed ).
  ENDMETHOD.                    "pedal_faster
ENDCLASS.                    "bicycle IMPLEMENTATION

*----------------------------------------------------------------------*
*       CLASS mountain_bike IMPLEMENTATION
*----------------------------------------------------------------------*
* Used to implement a Mountain Bike
*----------------------------------------------------------------------*
CLASS mountain_bike IMPLEMENTATION.
  METHOD constructor.
    " This calls the super class constructor passing this parameter
    " In the super class is our passenger_list and it will hand the creation
    " of the instance of that class.  You've got to love inheritance.
    " You get all that functionality for free from the super class.
    super->constructor( e_max_passengers ).

    " Initiate the gear systen for a mountain bike
    CREATE OBJECT l_gear_system EXPORTING e_max_gears = e_max_gears.
  ENDMETHOD.                    "constructor
  METHOD get_status.
    " This method was re-implemented and is more specific to a mountain bike

    DATA: l_speed TYPE vehicle=>lty_speed,
          l_current_gear TYPE gear_system=>lty_gear,
          l_passenger_status TYPE string,
          lo_passenger_list TYPE REF TO passenger_list.


    l_speed = get_current_speed( ).

    l_current_gear = l_gear_system->get_current_gear( ).

    lo_passenger_list = get_passengers_list( ).
    l_passenger_status = lo_passenger_list->get_status( ).


    CONCATENATE 'I am a mountain bike.  My current gear is'
                l_current_gear
                '.  My speed is'
                l_speed '.'
      INTO e_status SEPARATED BY space.

    CONCATENATE e_status l_passenger_status INTO e_status SEPARATED BY space.
  ENDMETHOD.                    "output_bicycle_status
  METHOD get_gear_system.
    i_gear_system = l_gear_system.
  ENDMETHOD.                    "get_gear_system
ENDCLASS.                    "mountain_bike IMPLEMENTATION

*----------------------------------------------------------------------*
*       CLASS road_bike IMPLEMENTATION
*----------------------------------------------------------------------*
* Used to implement road bike
*----------------------------------------------------------------------*
CLASS road_bike IMPLEMENTATION.
  METHOD constructor.
    " This calls the super class constructor passing this parameter
    " In the super class is our passenger_list and it will hand the creation
    " of the instance of that class.  You've got to love inheritance.
    " You get all that functionality for free from the super class.
    super->constructor( e_max_passengers ).

    " Initiate the gear systen for a mountain bike
    CREATE OBJECT l_gear_system EXPORTING e_max_gears = e_max_gears.
  ENDMETHOD.                    "constructor
  METHOD get_gear_system.
    i_gear_system = l_gear_system.
  ENDMETHOD.                    "get_gear_system
  METHOD get_status.
    " This method was re-implemented and is more specific to a mountain bike

    DATA: l_speed TYPE vehicle=>lty_speed,
          l_current_gear TYPE gear_system=>lty_gear,
          l_passenger_status TYPE string,
          lo_passenger_list TYPE REF TO passenger_list.

    l_speed = get_current_speed( ).

    l_current_gear = l_gear_system->get_current_gear( ).

    lo_passenger_list = get_passengers_list( ).
    l_passenger_status = lo_passenger_list->get_status( ).

    CONCATENATE 'I am a road bike.  My current gear is'
                l_current_gear
                '.  My speed is'
                l_speed '.'
      INTO e_status SEPARATED BY space.

    CONCATENATE e_status l_passenger_status INTO e_status SEPARATED BY space.
  ENDMETHOD.                    "output_bicycle_status

ENDCLASS.                    "road_bike IMPLEMENTATION

*----------------------------------------------------------------------*
*       CLASS tandem_bike IMPLEMENTATION
*----------------------------------------------------------------------*
* Used to implement tandem bike.  It took me 2 minutes to create all
* the code for this.  All thanks to inheritance
*----------------------------------------------------------------------*
CLASS tandem_bike IMPLEMENTATION.
  METHOD constructor.
    " This calls the super class constructor passing this parameter
    " In the super class is our passenger_list and it will hand the creation
    " of the instance of that class.  You've got to love inheritance.
    " You get all that functionality for free from the super class.
    super->constructor( e_max_passengers ).

  ENDMETHOD.                    "constructor

  METHOD get_status.
    " This method was re-implemented and is more specific to a tandem

    DATA: l_speed TYPE vehicle=>lty_speed,
          l_passenger_status TYPE string,
          lo_passenger_list TYPE REF TO passenger_list.

    l_speed = get_current_speed( ).

    lo_passenger_list = get_passengers_list( ).
    l_passenger_status = lo_passenger_list->get_status( ).

    CONCATENATE 'I am a tandem bike.'
                'My speed is'
                l_speed '.'
      INTO e_status SEPARATED BY space.

    CONCATENATE e_status l_passenger_status INTO e_status SEPARATED BY space.

  ENDMETHOD.                    "get_status
ENDCLASS.                    "tandem_bike DEFINITION

The result

It would look a bit like this. I just can't work out how to load an image here...

ZZZKP_DEMO_POLYMORPHISM

I am a mountain bike. My current gear is 02 . My speed is 0009 . My list of passengers includes: Katan Patel
I am a mountain bike. My current gear is 01 . My speed is 0020 . My list of passengers includes: Sherlock Holmes
I am a road bike. My current gear is 03 . My speed is 0015 . My list of passengers includes: James Bond

A Quick Recap on Interfaces

In its most common form, an interface is a group of related methods with empty bodies. Interfaces form a contract between the class and the outside world, and this contract is enforced at build time by the compiler.

If your class claims to implement an interface, all methods defined by that interface must appear in its source code before the class will successfully activate. A class can implement more than one interface.

Interface Polymorphism

In the same way that a class can be used to type a reference to an object. It is also possible to use an interface to type a reference to an object. You can only do this if your interface is implemented in the class that object was instantiated to. This also includes all super classes of the class. Thus polymorphism can be achieved via interfaces.

Similar to inheritance polymorphism, the downside of referencing an object via an interface that it implements, is that you lose the ability to access all methods of the class the object was instantiated with that are not defined in the interface.

Again similar to inheritance polymorphism, the upside is that you can still call methods available in the interface. The ABAP runtime can determine the class that the object was instantiated from and execute the implementation in this class.

When would you use this technique?

The main reason to use this is when you need to provide common functionality across unrelated classes. If you are to provide common functionality across related classes, it would make more sense to use inheritance instead.

Conclusion

By having a contract with developers who implement this interface with a tightly defined signature, we can guarantee they can develop a unit of code that will fit exactly within our existing code and can be accessed with reference to the interface.

I know that seems like a massive sentence to take in, so let's work it through in a demo.

Demo Bicycle Interface Polymorphism

In this program we define an interface "object_status" to allow any object that implements it to output it's status via the method "get_status".

We then have a complimentary class called "status_handler" that can be used to store references to any object that implements the interface "object_status".

In the demo program we add objects to the list and then can execute a method of list to output the statuses of all the objects in the list.

Now the beauty of this is that, as long as any class I use implements my list, I can use the list to store them and generate outputs. So if I create new classes I can reuse all of this logic, just by implementing the interface and it's method. Talk about getting something for free....

You can copy the below report and include programs into your system to check out how this works....

Error rendering macro 'code': Invalid value specified for parameter 'com.atlassian.confluence.ext.code.render.InvalidValueException'
*&---------------------------------------------------------------------*
*& Report  ZZZ_DEMO_INTERFACE
*&
*&---------------------------------------------------------------------*
*& In this example we have created an interface "object_status" to define
*& the methods for handling the output of status for objects. As interfaces
*& can be used for typing object instances any object that implements
*& this interface can assigned a reference with that type.  By implementing
*& the interface is like a contractually binding agreement that the
*& implementing class promises to provide the functionality outlined in the
*& interface definition
*&
*& We then have a class implemented that handles a list of objects
*& referenced to the type of the interface "status_handler".  Here we
*& have used the singleton design pattern to get us instances of itself
*& An instance of this class can be used to store any object that
*& implements interface "object_status" and output all the status for
*& each object in the list.  I can confidently know that any object
*& being passed here will implement the methods defined in the interface
*& and so I can call these within this class to provide functionality
*& to output statuses of all the objects listed
*&
*& The cool thing is that any new objects I create that implement this
*& can implicitly be used with the class "status_handler".  In short I
*& am using this technique for providing common functionality to
*& unrelated classes.
*&
*& One thing you cannot do with interfaces is change them once they are
*& created and released.  To provide common functionality among related
*& classes it is always better to use an abstract class
*&---------------------------------------------------------------------*

REPORT  zzz_demo_interface.

INCLUDE zzz_status_int_lib.
INCLUDE zzz_demo_gears_int_lib.
INCLUDE zzz_demo_passenger_int_lib.
INCLUDE zzz_demo_vehicle_int_lib.


*----------------------------------------------------------------------*
*       CLASS bicycle_demo DEFINITION
*----------------------------------------------------------------------*
* A class to execute the bicycle demo functionality
* This class is set as abstract as I do not want anyone extending
* the class or creating an instance of it as it makes no sense.
* It is only used to kick off the processing for this program
*----------------------------------------------------------------------*
CLASS bicycle_demo DEFINITION ABSTRACT FINAL.
  PUBLIC SECTION.
    CLASS-METHODS: run_demo.
ENDCLASS.                    "bicycle_demo DEFINITION

*----------------------------------------------------------------------*
*       CLASS bicycle_demo IMPLEMENTATION
*----------------------------------------------------------------------*
* Implement the bicycle demo functionaility.  Here I am creating
* all of these objects which implement the object_status interface
* I am then adding them to a status_handler_list although tehy are not
* explicitly typed as status_handler, because the class they belong to
* implements the interface
*----------------------------------------------------------------------*
CLASS bicycle_demo IMPLEMENTATION.
  METHOD run_demo.

    DATA: lo_mountain_bike TYPE REF TO mountain_bike,
          lo_road_bike TYPE REF TO road_bike,
          lo_gear_system TYPE REF TO gear_system,
          lo_passenger TYPE REF TO passenger,
          lo_passenger_list TYPE REF TO passenger_list,
          lo_status_handler type REF TO status_handler.

    " Get an instance of status handler
    " This class was implemented using the singleton design pattern
    " so I get the instance via method "get_instance"
    lo_status_handler = status_handler=>get_instance( ).

    " Create a new instance of mountain bike and take it for a spin
    CREATE OBJECT lo_mountain_bike EXPORTING  e_max_passengers = 1
                                              e_max_gears = 10.
    " Get the reference to the passengers list for the mountain bike
    " and assign it to the passenger list field then add a new passenger
    lo_passenger_list = lo_mountain_bike->get_passengers_list( ).
    lo_passenger_list->add_passenger_by_name( e_first_name = 'Katan' e_last_name = 'Patel' ).
    " Get the reference to the gear system for the mountain bike
    " and assign it to the gear_system field
    lo_gear_system = lo_mountain_bike->get_gear_system( ).
    lo_mountain_bike->pedal_faster( 10 ).
    lo_gear_system->change_gear_up( ).
    lo_gear_system->change_gear_up( ).
    lo_mountain_bike->apply_brakes( 1 ).
    lo_status_handler->add_object_to_monitor( lo_mountain_bike ).
    FREE: lo_mountain_bike, lo_gear_system, lo_passenger_list.

    " Create another instance of mountain bike and take it for a spin
    CREATE OBJECT lo_mountain_bike EXPORTING e_max_passengers = 1
                                             e_max_gears = 18.
    " Get the reference to the passengers list for the mountain bike
    " and assign it to the passenger list field then add a new passenger
    lo_passenger_list = lo_mountain_bike->get_passengers_list( ).
    lo_passenger_list->add_passenger_by_name( e_first_name = 'Sherlock' e_last_name = 'Holmes' ).
    " Get the reference to the gear system for the mountain bike
    " and assign it to the gear_system field
    lo_gear_system = lo_mountain_bike->get_gear_system( ).
    lo_mountain_bike->pedal_faster( 20 ).
    lo_gear_system->change_gear_up( ).
    " Add the mountain bike to the status handler method
    lo_status_handler->add_object_to_monitor( lo_mountain_bike ).
    FREE: lo_mountain_bike, lo_gear_system, lo_passenger_list.

    "Create a new instance of Road bike and take it for a spin
    CREATE OBJECT lo_road_bike EXPORTING e_max_passengers = 1
                                         e_max_gears = 20.
    " Get the reference to the passengers list for the mountain bike
    " and assign it to the passenger list field then add a new passenger
    lo_passenger_list = lo_road_bike->get_passengers_list( ).
    lo_passenger_list->add_passenger_by_name( e_first_name = 'James' e_last_name = 'Bond' ).
    " Get the reference to the gear system for the mountain bike
    " and assign it to the gear_system field
    lo_gear_system = lo_road_bike->get_gear_system( ).
    lo_road_bike->pedal_faster( 20 ).
    lo_gear_system->change_gear_up( ).
    lo_gear_system->change_gear_up( ).
    lo_gear_system->change_gear_up( ).
    lo_road_bike->apply_brakes( 5 ).
    " Add the mountain bike to the status handler method
    lo_status_handler->add_object_to_monitor( lo_road_bike ).
    FREE: lo_road_bike, lo_gear_system, lo_passenger_list.

    " Create a passenger list object
    CREATE OBJECT lo_passenger_list
      EXPORTING e_max_passengers = 5.
    " Add some passengers
    lo_passenger_list->add_passenger_by_name( e_first_name = 'Harry' e_last_name = 'Potter' ).
    lo_passenger_list->add_passenger_by_name( e_first_name = 'Mary' e_last_name = 'Poppins' ).
    lo_passenger_list->add_passenger_by_name( e_first_name = 'Basil' e_last_name = 'Fawlty' ).
    " Add the passenger objects to my object_status table.
    lo_status_handler->add_object_to_monitor( lo_passenger_list ).
    FREE: lo_passenger_list.

    " Execute this method to output the status for all the objects added to
    " the status handler list
    lo_status_handler->output_status_for_all_objs( ).

  ENDMETHOD.                    "run_demo
ENDCLASS.                    "bicycle_demo IMPLEMENTATION


START-OF-SELECTION.
  " This is not required if you are not running a report
  " without using the classic list processing
  " Instead use an ALV as output and use an OO transaction
  " code instead.  It must call a static class method like
  " our run_demo
  bicycle_demo=>run_demo( ).
Error rendering macro 'code': Invalid value specified for parameter 'com.atlassian.confluence.ext.code.render.InvalidValueException'
*&---------------------------------------------------------------------*
*&  Include           ZZZ_DEMO_GEARS_INT_LIB
*&---------------------------------------------------------------------*

*** Class Definitions ***
*----------------------------------------------------------------------*
*       CLASS gear_system DEFINITION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS gear_system DEFINITION.
  PUBLIC SECTION.
    TYPES: lty_gear(2) TYPE n.

    METHODS: constructor IMPORTING e_max_gears TYPE gear_system=>lty_gear,
             change_gear_up,
             change_gear_down,
             get_current_gear RETURNING value(e_current_gear) TYPE lty_gear.

    INTERFACES: object_status.

  PRIVATE SECTION.
    DATA: l_current_gear TYPE lty_gear,
          l_max_gears TYPE lty_gear.
ENDCLASS.                    "gear_system DEFINITION

*** Class Implementations ***
*----------------------------------------------------------------------*
*       CLASS gear_system IMPLEMENTATION
*----------------------------------------------------------------------*
* Class defines a generic gear system for use in any object that uses
* gears
*----------------------------------------------------------------------*
CLASS gear_system IMPLEMENTATION.
  METHOD constructor.
    l_max_gears = e_max_gears.
  ENDMETHOD.                    "constructor
  METHOD change_gear_up.
    l_current_gear = l_current_gear + 1.
  ENDMETHOD.                    "change_gear_up
  METHOD change_gear_down.
    l_current_gear = l_current_gear - 1.
  ENDMETHOD.                    "change_gear_down
  METHOD get_current_gear.  "This is the only way to access this field of the class
    e_current_gear = l_current_gear.
  ENDMETHOD.                    "get_current_gear
  METHOD object_status~get_status.
    CONCATENATE 'My gear system has ' l_max_gears
                'and is currently in gear' l_current_gear
      INTO i_status SEPARATED BY space.
  ENDMETHOD.                    "object_status~get_status
ENDCLASS.                    "gear_system IMPLEMENTATION

Error rendering macro 'code': Invalid value specified for parameter 'com.atlassian.confluence.ext.code.render.InvalidValueException'
*&---------------------------------------------------------------------*
*&  Include           ZZZ_DEMO_PASSENGER_INT_LIB
*&---------------------------------------------------------------------*


*----------------------------------------------------------------------*
*       CLASS passenger DEFINITION
*----------------------------------------------------------------------*
* A generic class for a passenger.
*----------------------------------------------------------------------*
CLASS passenger DEFINITION.
  PUBLIC SECTION.
    TYPES: lty_name TYPE string,
           lty_dest TYPE string.

    METHODS: constructor IMPORTING e_first_name TYPE lty_name
                                   e_last_name TYPE lty_name,
             set_first_name IMPORTING e_first_name TYPE lty_name,
             set_last_name IMPORTING e_last_name TYPE lty_name,
             get_full_name RETURNING value(i_full_name) TYPE lty_name,
             set_current_destination IMPORTING e_destination TYPE lty_dest,
             get_current_destination EXPORTING i_destination TYPE lty_dest.

  PRIVATE SECTION.
    DATA: l_first_name TYPE lty_name,
          l_last_name TYPE lty_name,
          l_current_destination TYPE lty_dest.
ENDCLASS.                    "passenger DEFINITION


*----------------------------------------------------------------------*
*       CLASS passenger_list DEFINITION
*----------------------------------------------------------------------*
*  A class to manage a list of passengers.  This should not be extended
* thus it is set as final.  It handles the management of all passengers
* I can use this in other objects and not worry about this when using
* instances of this class
*----------------------------------------------------------------------*
CLASS passenger_list DEFINITION FINAL.
  PUBLIC SECTION.
    TYPES: BEGIN OF lty_passengers,
             full_name TYPE passenger=>lty_name,
             passenger TYPE REF TO passenger,
           END OF lty_passengers,
           ltty_passengers TYPE SORTED TABLE OF lty_passengers
            WITH UNIQUE KEY full_name.

    INTERFACES: object_status.

    METHODS: constructor IMPORTING e_max_passengers TYPE i,
             add_passenger IMPORTING e_passenger TYPE REF TO passenger
                           RETURNING value(i_added_successfully) TYPE REF TO cl_boolean,
             add_passenger_by_name IMPORTING e_first_name TYPE passenger=>lty_name
                                             e_last_name TYPE passenger=>lty_name
                           RETURNING value(i_added_successfully) TYPE REF TO cl_boolean,
             remove_passenger IMPORTING e_passenger TYPE REF TO passenger
                              RETURNING value(i_removed_successfully) TYPE REF TO cl_boolean,
             check_passenger_exists IMPORTING e_passenger TYPE REF TO passenger
                                    RETURNING value(i_does_exist) TYPE REF TO cl_boolean,
             set_max_passengers IMPORTING e_max_passengers TYPE i,
             get_max_passengers EXPORTING i_max_passengers TYPE i.

  PRIVATE SECTION.
    DATA: lt_passengers TYPE ltty_passengers,
          l_max_passengers TYPE i.

ENDCLASS.                    "passenger_list DEFINITION

*----------------------------------------------------------------------*
*       CLASS passenger IMPLEMENTATION
*----------------------------------------------------------------------*
*  The implementation of the passenger
*----------------------------------------------------------------------*
CLASS passenger IMPLEMENTATION.
  METHOD constructor.
    l_first_name = e_first_name.
    l_last_name = e_last_name.
  ENDMETHOD.                    "constructor
  METHOD set_first_name.
    l_first_name = e_first_name.
  ENDMETHOD.                    "set_first_name
  METHOD set_last_name.
    l_last_name = e_last_name.
  ENDMETHOD.                    "set_last_name
  METHOD get_full_name.
    CONCATENATE l_first_name l_last_name INTO i_full_name
        SEPARATED BY space.
  ENDMETHOD.                    "get_full_name
  METHOD set_current_destination.
    l_current_destination = e_destination.
  ENDMETHOD.                    "set_current_destination
  METHOD get_current_destination.
    i_destination = l_current_destination.
  ENDMETHOD.                    "get_current_destination
ENDCLASS.                    "passenger IMPLEMENTATION

*----------------------------------------------------------------------*
*       CLASS passenger_list IMPLEMENTATION
*----------------------------------------------------------------------*
*  The implementation of class passenger_list
*----------------------------------------------------------------------*
CLASS passenger_list IMPLEMENTATION.
  METHOD constructor.
    l_max_passengers = e_max_passengers.
  ENDMETHOD.                    "constructor
  METHOD check_passenger_exists.
    DATA: l_full_name TYPE passenger=>lty_name.

    "Implicitly this should be false
    i_does_exist = cl_boolean=>false.

    " Get the passengers full name
    l_full_name = e_passenger->get_full_name( ).

    " Read the table to see if an entry already exists for the passenger
    READ TABLE lt_passengers
      WITH TABLE KEY full_name = l_full_name
      TRANSPORTING NO FIELDS.

    " If it does exist then set it to true
    IF sy-subrc = 0.
      i_does_exist = cl_boolean=>true.
    ENDIF.
  ENDMETHOD.                    "check_passenger_exists
  METHOD add_passenger.
    DATA: l_full_name TYPE passenger=>lty_name,
          l_passenger_record TYPE lty_passengers,
          l_no_records TYPE i.

    DESCRIBE TABLE lt_passengers LINES l_no_records.
    IF l_no_records = l_max_passengers.
      WRITE:/ 'Too many passengers on board.  No record added'.
      EXIT.
    ENDIF.

    "Implicitly this should be false
    i_added_successfully = cl_boolean=>false.

    "If the passenger does not already exist we can add it
    IF check_passenger_exists( e_passenger ) = cl_boolean=>false.
      l_passenger_record-full_name = e_passenger->get_full_name( ).
      l_passenger_record-passenger = e_passenger.
      INSERT l_passenger_record INTO TABLE lt_passengers .

      i_added_successfully = cl_boolean=>true.
    ELSE.
      WRITE:/ 'Passenger ', l_full_name, ' already exists'.
    ENDIF.
  ENDMETHOD.                    "add_passenger
  METHOD remove_passenger.
    DATA: l_full_name TYPE passenger=>lty_name.

    " Get the passengers full name
    l_full_name = e_passenger->get_full_name( ).

    "Implicitly this should be false
    i_removed_successfully = cl_boolean=>false.

    "If the passenger does not already exist we can add it
    IF check_passenger_exists( e_passenger ) = cl_boolean=>true.
      DELETE lt_passengers
        WHERE full_name = l_full_name.
      i_removed_successfully = cl_boolean=>true.
    ELSE.
      WRITE:/ 'Passenger ', l_full_name, ' does not exist'.
    ENDIF.
  ENDMETHOD.                    "remove_passenger
  METHOD set_max_passengers.
    l_max_passengers = e_max_passengers.
  ENDMETHOD.                    "set_max_passengers
  METHOD get_max_passengers.
    i_max_passengers = l_max_passengers.
  ENDMETHOD.                    "get_max_passengers
  METHOD add_passenger_by_name.
    "This method acts as a quick way to create passengers and add them
    " to my list
    DATA: lo_passenger TYPE REF TO passenger.

    CREATE OBJECT lo_passenger EXPORTING e_first_name = e_first_name
                                         e_last_name = e_last_name.
    add_passenger( lo_passenger ).
  ENDMETHOD.                    "add_passenger_by_name
  METHOD object_status~get_status.
    DATA: l_full_name TYPE passenger=>lty_name.

    FIELD-SYMBOLS: <fs_passenger> TYPE lty_passengers.

    i_status = 'My list of passengers includes: '.

    " Loop through all the passengers and return a string of passengers
    LOOP AT lt_passengers ASSIGNING <fs_passenger>.
      l_full_name = <fs_passenger>-passenger->get_full_name( ).
      IF sy-tabix = 1.
        CONCATENATE i_status l_full_name INTO i_status SEPARATED BY space.
      ELSE.
        CONCATENATE i_status ',' l_full_name INTO i_status SEPARATED BY space.
      ENDIF.
    ENDLOOP.
    IF sy-subrc <> 0.
      i_status = 'I have no passengers'.
    ENDIF.
  ENDMETHOD.                    "get_status
ENDCLASS.                    "passenger_list IMPLEMENTATION
Error rendering macro 'code': Invalid value specified for parameter 'com.atlassian.confluence.ext.code.render.InvalidValueException'
*&---------------------------------------------------------------------*
*&  Include           ZZZ_DEMO_VEHICLE_INT_LIB
*&---------------------------------------------------------------------*

*** Class Definitions ***
*----------------------------------------------------------------------*
*       CLASS vehicle DEFINITION
*----------------------------------------------------------------------*
* A generic implementation for vehicles
*----------------------------------------------------------------------*
CLASS vehicle DEFINITION.
  PUBLIC SECTION.
    TYPES: lty_speed(4) TYPE n.

    METHODS: constructor IMPORTING eo_max_passengers TYPE i,
    speed_up IMPORTING e_increment_speed TYPE lty_speed,
    slow_down IMPORTING e_decrement_speed TYPE lty_speed,
    get_current_speed RETURNING value(i_current_speed) TYPE lty_speed,
    get_passengers_list RETURNING value(io_passenger_list) TYPE REF TO passenger_list.

  PRIVATE SECTION.
    DATA: l_speed TYPE lty_speed,
          lo_passengers_list TYPE REF TO passenger_list.

ENDCLASS.                    "vehicle DEFINITION

*----------------------------------------------------------------------*
*       CLASS bicycle DEFINITION
*----------------------------------------------------------------------*
* A class for bicycles.  This is a sub class of vehicle
*----------------------------------------------------------------------*
CLASS bicycle DEFINITION INHERITING FROM vehicle.
  PUBLIC SECTION.
    INTERFACES: object_status.

    METHODS: pedal_faster IMPORTING e_increment_speed TYPE vehicle=>lty_speed,
             apply_brakes IMPORTING e_decrement_speed TYPE vehicle=>lty_speed.
ENDCLASS.                    "bicycle DEFINITION

*----------------------------------------------------------------------*
*       CLASS mountain_bike DEFINITION
*----------------------------------------------------------------------*
* Mountain bikes have gears and so gear system is an attribute of
* mountain bike class.  This is a subclass of bicycle
*----------------------------------------------------------------------*
CLASS mountain_bike DEFINITION INHERITING FROM bicycle.

  PUBLIC SECTION.
    METHODS: constructor IMPORTING e_max_passengers TYPE i
                                   e_max_gears TYPE gear_system=>lty_gear,
             object_status~get_status REDEFINITION,
             get_gear_system RETURNING value(i_gear_system) TYPE REF TO gear_system.

  PRIVATE SECTION.
    DATA: l_gear_system TYPE REF TO gear_system.

ENDCLASS.                    "mountain_bike DEFINITION

*----------------------------------------------------------------------*
*       CLASS road_bike DEFINITION
*----------------------------------------------------------------------*
*   This is a subclass of bicycle
*----------------------------------------------------------------------*
CLASS road_bike DEFINITION INHERITING FROM bicycle.
  PUBLIC SECTION.
    METHODS: constructor IMPORTING e_max_passengers TYPE i
                          e_max_gears TYPE gear_system=>lty_gear,
             object_status~get_status REDEFINITION,
             get_gear_system RETURNING value(i_gear_system) TYPE REF TO gear_system.

  PRIVATE SECTION.
    DATA: l_gear_system TYPE REF TO gear_system.
ENDCLASS.                    "road_bike DEFINITION

*** Class Implementations ***
*----------------------------------------------------------------------*
*       CLASS vehicle IMPLEMENTATION
*----------------------------------------------------------------------*
* Superclass of all vehicles
*----------------------------------------------------------------------*
CLASS vehicle IMPLEMENTATION.
  METHOD constructor.
    CREATE OBJECT lo_passengers_list
        EXPORTING e_max_passengers = eo_max_passengers.
  ENDMETHOD.                    "constructor
  METHOD speed_up.
    l_speed = l_speed + e_increment_speed.
  ENDMETHOD.                    "speed_up
  METHOD slow_down.
    l_speed = l_speed - e_decrement_speed.

    "Speed cannot be less than 0
    IF l_speed LT 0.
      l_speed = 0.
    ENDIF.
  ENDMETHOD.                    "apply_breaks
  METHOD get_current_speed.
    i_current_speed = l_speed.
  ENDMETHOD.                    "get_current_speed
  METHOD get_passengers_list.
    io_passenger_list = lo_passengers_list.
  ENDMETHOD.                    "get_passengers_list
ENDCLASS.                    "vehicle IMPLEMENTATION


*----------------------------------------------------------------------*
*       CLASS bicycle IMPLEMENTATION
*----------------------------------------------------------------------*
* Superclass of all bicycles
*----------------------------------------------------------------------*
CLASS bicycle IMPLEMENTATION.
  METHOD object_status~get_status.
    DATA: l_output TYPE string,
          l_speed TYPE vehicle=>lty_speed.

    l_speed = get_current_speed( ).

    CONCATENATE 'I am a bicycle.  My speed is' l_speed
      INTO i_status SEPARATED BY space.
  ENDMETHOD.                    "output_bicycle_status
  METHOD apply_brakes.
    me->slow_down( e_decrement_speed ).
  ENDMETHOD.                    "apply_breaks
  METHOD pedal_faster.
    me->speed_up( e_increment_speed ).
  ENDMETHOD.                    "pedal_faster
ENDCLASS.                    "bicycle IMPLEMENTATION

*----------------------------------------------------------------------*
*       CLASS mountain_bike IMPLEMENTATION
*----------------------------------------------------------------------*
* Used to implement a Mountain Bike
*----------------------------------------------------------------------*
CLASS mountain_bike IMPLEMENTATION.
  METHOD constructor.
    " This calls the super class constructor passing this parameter
    " In the super class is our passenger_list and it will hand the creation
    " of the instance of that class.  You've got to love inheritance.
    " You get all that functionality for free from the super class.
    super->constructor( e_max_passengers ).

    " Initiate the gear systen for a mountain bike
    CREATE OBJECT l_gear_system EXPORTING e_max_gears = e_max_gears.
  ENDMETHOD.                    "constructor
  METHOD object_status~get_status.
    " This method was re-implemented and is more specific to a mountain bike

    DATA: l_speed TYPE vehicle=>lty_speed,
          l_current_gear TYPE gear_system=>lty_gear,
          l_passenger_status TYPE string,
          lo_passenger_list TYPE REF TO passenger_list.


    l_speed = get_current_speed( ).

    l_current_gear = l_gear_system->get_current_gear( ).

    lo_passenger_list = get_passengers_list( ).
    l_passenger_status = lo_passenger_list->object_status~get_status( ).


    CONCATENATE 'I am a mountain bike.  My current gear is'
                l_current_gear
                '.  My speed is'
                l_speed '.'
      INTO i_status SEPARATED BY space.

    CONCATENATE i_status l_passenger_status INTO i_status SEPARATED BY space.
  ENDMETHOD.                    "output_bicycle_status
  METHOD get_gear_system.
    i_gear_system = l_gear_system.
  ENDMETHOD.                    "get_gear_system
ENDCLASS.                    "mountain_bike IMPLEMENTATION

*----------------------------------------------------------------------*
*       CLASS road_bike IMPLEMENTATION
*----------------------------------------------------------------------*
* Used to implment road bike
*----------------------------------------------------------------------*
CLASS road_bike IMPLEMENTATION.
  METHOD constructor.
    " This calls the super class constructor passing this parameter
    " In the super class is our passenger_list and it will hand the creation
    " of the instance of that class.  You've got to love inheritance.
    " You get all that functionality for free from the super class.
    super->constructor( e_max_passengers ).

    " Initiate the gear systen for a mountain bike
    CREATE OBJECT l_gear_system EXPORTING e_max_gears = e_max_gears.
  ENDMETHOD.                    "constructor
  METHOD get_gear_system.
    i_gear_system = l_gear_system.
  ENDMETHOD.                    "get_gear_system
  METHOD object_status~get_status.
    " This method was re-implemented and is more specific to a mountain bike

    DATA: l_speed TYPE vehicle=>lty_speed,
          l_current_gear TYPE gear_system=>lty_gear,
          l_passenger_status TYPE string,
          lo_passenger_list TYPE REF TO passenger_list.

    l_speed = get_current_speed( ).

    l_current_gear = l_gear_system->get_current_gear( ).

    lo_passenger_list = get_passengers_list( ).
    l_passenger_status = lo_passenger_list->object_status~get_status( ).

    CONCATENATE 'I am a road bike.  My current gear is'
                l_current_gear
                '.  My speed is'
                l_speed '.'
      INTO i_status SEPARATED BY space.

    CONCATENATE i_status l_passenger_status INTO i_status SEPARATED BY space.
  ENDMETHOD.                    "output_bicycle_status

ENDCLASS.                    "road_bike IMPLEMENTATION
Error rendering macro 'code': Invalid value specified for parameter 'com.atlassian.confluence.ext.code.render.InvalidValueException'
*&---------------------------------------------------------------------*
*&  Include           ZZZ_STATUS_INT_LIB
*&---------------------------------------------------------------------*
INTERFACE object_status.
  METHODS: get_status RETURNING value(i_status) TYPE string.
ENDINTERFACE.                    "object_status

*----------------------------------------------------------------------*
*       CLASS status_handler DEFINITION
*----------------------------------------------------------------------*
* A class to manage the handling of statuses of objects
*----------------------------------------------------------------------*
CLASS status_handler DEFINITION CREATE PRIVATE.
  PUBLIC SECTION.
    " Create a structured type of interface object_status
    " and also a table type based on the structured type
    TYPES: BEGIN OF lty_object_status,
             object_status TYPE REF TO object_status,
           END OF lty_object_status,
           ltty_objects TYPE STANDARD TABLE OF lty_object_status.

    CLASS-METHODS: get_instance RETURNING value(i_obj_stat)
                      TYPE REF TO status_handler.

    METHODS: add_object_to_monitor
                  IMPORTING e_object TYPE REF TO object_status,
             free_objects_to_monitor,
             output_status_for_all_objs.

  PRIVATE SECTION.
    CLASS-DATA: lo_status_handler TYPE REF TO status_handler.

    DATA: lt_object_status TYPE ltty_objects.
ENDCLASS.                    "status_handler DEFINITION

*----------------------------------------------------------------------*
*       CLASS status_handler IMPLEMENTATION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS status_handler IMPLEMENTATION.
  METHOD get_instance.
    IF lo_status_handler IS INITIAL.
      CREATE OBJECT lo_status_handler.
    ENDIF.
    i_obj_stat = lo_status_handler.
  ENDMETHOD.                    "get_instance
  METHOD add_object_to_monitor.
    " This method can be used to store references to object_status objects
    DATA: l_object_status_record TYPE lty_object_status.

    l_object_status_record-object_status = e_object.
    APPEND l_object_status_record TO lt_object_status.

  ENDMETHOD.                    "add_object_to_monitor
  " This method can be used to delete all references to objects of object_status
  " stored in the list for monitoring
  METHOD free_objects_to_monitor.
    FREE: lt_object_status.
  ENDMETHOD.                    "free_objects_to_monitor
  METHOD output_status_for_all_objs.
    DATA: l_status TYPE string.
    " Always better to use field symbols for looping
    " much better performance
    FIELD-SYMBOLS: <fs_object_status> TYPE lty_object_status.

    " The impressive bit...
    " I can reference any objects that implement interface object_status via interface
    " inheritance.  Here I am looping through all my objects and executing output_status.
    " However if you run this, you will see different outputs are generated depending on the
    " type on the actual object being processed.  It it this ability that is polymorphism but via interfaces.
    " You can see that the ABAP runtime determines the correct method to execute by finding the
    " lowest possible implementation of the method "output_bicycle_status" for each of
    " the objects.  Referencing these objects via the interface does not mean that I cannot convert
    " them back later and use them as their respective objects. You will see in my later examples
    " how it is possible to convert them back
    LOOP AT lt_object_status ASSIGNING <fs_object_status>.
      l_status = <fs_object_status>-object_status->get_status( ).
      WRITE:/ l_status.
    ENDLOOP.

  ENDMETHOD.                    "output_status_for_monitored_objs
ENDCLASS.                    "status_handler IMPLEMENTATION

The Result

It would look a bit like this.

Program ZZZKP_DEMO_INTERFACE

I am a mountain bike. My current gear is 02 . My speed is 0009 . My list of passengers includes: Katan Patel
I am a mountain bike. My current gear is 01 . My speed is 0020 . My list of passengers includes: Sherlock Holmes
I am a road bike. My current gear is 03 . My speed is 0015 . My list of passengers includes: James Bond
My list of passengers includes: Harry Potter , Mary Poppins , Basil Fawlty

Hi, most of the people here on SCN try to learn object oriented programming through various available sources. I have also tried a lot to learn this beautiful OOP feature and still learning it. Even I have gone through various SAP Press Books to summarize all the aspects of it. Here I have prepared a small set of information that would be useful before, after and in-between phase of learning OOP. It also helps you to get quick understanding of any topic before you go in depth. I have not explained global class here that is skipped intentionally for your practice with reference to local class. Please check all sample abap code. As I said I am also learning so I may not give you some of your queries so please bear with me and help me to improve this document so that everyone can get benefit from it. I always try to provide best details to you if possible. Thank you.

 

Class

A class is an abstract representation, or, a set of instructions for building objects

Object

Objects are instances of classes. There can be any number of objects or instances in a class. Each object has a unique identity and its own attributes.

Encapsulation

Visibility (public, protected, private)

Inheritance

Inheritance allows you to derive a new class from an existing class.

Polymorphism

Overriding methods / redefining method - after inheriting / Interface.

Abstract

        Definition of a class cannot generate instance. You can only 

        Use an abstract class to create subclass.

Friend-Defined

 Access private attributes of another class.

Event

Invoke methods of same or other class.

Interface

Cannot have implementation, just the definition.

Exception

Static check-(check both at runtime and compile time), Dynamic check (only checks at runtime), No check (for all kind of exceptions). using CX_ROOT class

Levels

Instance, static, Constant.

Test class / Test methods

unit test (Test method class CL_AUNIT_ASSERT, #AU_DURATION_SHORT, #AU_RISK_LEVEL HARMLESS)

Persistent Class

Agent class, Base class, Class.

Refactoring Assistant

Add new class above any existing class.

Object parameters

Importing/Exporting/Returning-(receiving)/Exception and Raising

 

 

Additional Points.

->Static data shares common value across any number of its object, and it is only accessible inside static method or via => operator (cls_name=>static attribute).

->Multiple inheritance is not supported by abap (we may use interface to achieve this).

->In object parameter: Exception is non-class base exception which is triggered with statement raise / message raising.

->In object parameter: Raising is class base exception which is triggered with statement raise / message raising.

->The tilde (~) between the interface name and the interface component name is called the interface component selector operator.

->In persistent the class builder also generates a couple of additional agent classes that manage all of the low-level interaction details between objects of the persistent class and the Persistence Service.

->objects of persistent classes are referred to as managed objects.

->Transaction persistent service (We can insert data directly from persistent class to dB table using Tcode). IF_OS_TRANSACTION & IF_OS_TRANSACTION_MANAGER

General OOP Course Content that you should know:

 

  1. Class and object creation.
  2. Encapsulation (Public, Protected, Private).
  3. Constructor.
  4. Class method / class data.
  5. Final class - cannot be inherited any more.
  6. Final method - cannot be redefined any more.
  7. Inheritance.
  8. Using of super keyword.
  9. Interface.
  10. Exception handling using cx_root class.
  11. Test methods
  12. Persistent class
  13. Refactoring assistant
  14. Serialization - XML Transformation
  15. MVC pattern

 

Program Samples Index.

  • Class
  • Encapsulation
  • Inheritance
  • Polymorphism
  • Super keyword
  • Abstract
  • Friend-Deferred
  • Event
  • Interface
  • Exception
  • Test class / Test methods
  • Object parameters - Part 1
  • Object parameters - Part 2
  • MVC Pattern

 

Program Samples.

 

1.Class.

 

REPORT ZAVI_LOGIC.

CLASS CLS1 DEFINITION.
    PUBLIC SECTION.
      METHODS: METH1.
  ENDCLASS.

  CLASS CLS1 IMPLEMENTATION.
    METHOD METH1.
        WRITE : / 'OK'.
      ENDMETHOD.
    ENDCLASS.

START-OF-SELECTION.

    DATA : OBJ1 TYPE REF TO CLS1.
    CREATE OBJECT OBJ1.

    CALL METHOD OBJ1->METH1.

 

 

2. Encapsulation.

 

REPORT ZAVI_LOGIC.

CLASS CLS1 DEFINITION.
  PUBLIC SECTION.
    METHODS: METH1.
  PROTECTED SECTION.
    METHODS: METH2.
  PRIVATE SECTION.
    METHODS: METH3.
ENDCLASS.                    "CLS1 DEFINITION

CLASS CLS1 IMPLEMENTATION.
  METHOD METH1.
    WRITE : / 'OK - in public'.
  ENDMETHOD.                                                "METH1

  METHOD METH2.
    WRITE : / 'OK - in protected'.
  ENDMETHOD.                                                "METH2

  METHOD METH3.
    WRITE : / 'OK -  in private'.
  ENDMETHOD.                                                "METH3
ENDCLASS.                    "CLS1 IMPLEMENTATION

START-OF-SELECTION.

  DATA : OBJ1 TYPE REF TO CLS1.
  CREATE OBJECT OBJ1.
  CALL METHOD OBJ1->METH1.

 

 

3. Inheritance

 

REPORT ZAVI_LOGIC.

CLASS CLS1 DEFINITION.
  PUBLIC SECTION.
    METHODS: METH1.
  PROTECTED SECTION.
    METHODS: METH2.
  PRIVATE SECTION.
    METHODS: METH3.
ENDCLASS.                    "CLS1 DEFINITION

CLASS CLS1 IMPLEMENTATION.
  METHOD METH1.
    WRITE : / 'OK - in public'.
  ENDMETHOD.                                                "METH1

  METHOD METH2.
    WRITE : / 'OK - in protected'.
  ENDMETHOD.                                                "METH2

  METHOD METH3.
    WRITE : / 'OK -  in private'.
  ENDMETHOD.                                                "METH3
ENDCLASS.                    "CLS1 IMPLEMENTATION


class CLS2 DEFINITION INHERITING FROM CLS1.
  PUBLIC SECTION.
    METHODS: METH4.
ENDCLASS.

CLASS CLS2 IMPLEMENTATION.
    METHOD METH4.
        WRITE : / 'OK - in class2 public'.
    ENDMETHOD.
ENDCLASS.

START-OF-SELECTION.

  DATA : OBJ1 TYPE REF TO CLS2.
  CREATE OBJECT OBJ1.
  CALL METHOD OBJ1->METH1.
  CALL METHOD OBJ1->METH4.

 

 

4.Polymorphism

 

REPORT ZAVI_LOGIC.

CLASS CLS1 DEFINITION.
  PUBLIC SECTION.
    METHODS: METH1.
  PROTECTED SECTION.
    METHODS: METH2.
  PRIVATE SECTION.
    METHODS: METH3.
ENDCLASS.                    "CLS1 DEFINITION

CLASS CLS1 IMPLEMENTATION.
  METHOD METH1.
    WRITE : / 'OK - in public'.
  ENDMETHOD.                                                "METH1

  METHOD METH2.
    WRITE : / 'OK - in protected'.
  ENDMETHOD.                                                "METH2

  METHOD METH3.
    WRITE : / 'OK -  in private'.
  ENDMETHOD.                                                "METH3
ENDCLASS.                    "CLS1 IMPLEMENTATION


class CLS2 DEFINITION INHERITING FROM CLS1.
  PUBLIC SECTION.
    METHODS: METH4.
    METHODS: METH1 REDEFINITION.
ENDCLASS.

CLASS CLS2 IMPLEMENTATION.
    METHOD METH4.
        WRITE : / 'OK - in class2 public'.
    ENDMETHOD.

    METHOD METH1.
      WRITE : / 'OK - in class2 public - Redefine meth1 of class1'.
    ENDMETHOD.
ENDCLASS.

START-OF-SELECTION.

  DATA : OBJ1 TYPE REF TO CLS2.
  CREATE OBJECT OBJ1.
  CALL METHOD OBJ1->METH1.
  CALL METHOD OBJ1->METH4.

 

 

5.Super keyword

 

REPORT ZAVI_LOGIC.

CLASS CLS1 DEFINITION.
  PUBLIC SECTION.
    METHODS: METH1.
  PROTECTED SECTION.
    METHODS: METH2.
  PRIVATE SECTION.
    METHODS: METH3.
ENDCLASS.                    "CLS1 DEFINITION

CLASS CLS1 IMPLEMENTATION.
  METHOD METH1.
    WRITE : / 'OK - in public'.
  ENDMETHOD.                                                "METH1

  METHOD METH2.
    WRITE : / 'OK - in protected'.
  ENDMETHOD.                                                "METH2

  METHOD METH3.
    WRITE : / 'OK -  in private'.
  ENDMETHOD.                                                "METH3
ENDCLASS.                    "CLS1 IMPLEMENTATION


class CLS2 DEFINITION INHERITING FROM CLS1.
  PUBLIC SECTION.
    METHODS: METH4.
    METHODS: METH1 REDEFINITION.
ENDCLASS.

CLASS CLS2 IMPLEMENTATION.
    METHOD METH4.
        WRITE : / 'OK - in class2 public'.
    ENDMETHOD.

    METHOD METH1.
      WRITE : / 'OK - in class2 public - Redefine meth1 of class1'.
      CALL METHOD SUPER->METH1.
    ENDMETHOD.
ENDCLASS.

START-OF-SELECTION.

  DATA : OBJ1 TYPE REF TO CLS2.
  CREATE OBJECT OBJ1.
  CALL METHOD OBJ1->METH1.
  CALL METHOD OBJ1->METH4.

 

 

6.Abstract

 

REPORT ZAVI_LOGIC.
class cls0 DEFINITION ABSTRACT.
  PUBLIC SECTION.
    METHODS: METH0.
ENDCLASS.

CLASS CLS0 IMPLEMENTATION.
    METHOD METH0.
        WRITE : / 'Inside Abstract'.
      ENDMETHOD.
ENDCLASS.

CLASS CLS1 DEFINITION INHERITING FROM cls0.
  PUBLIC SECTION.
    METHODS: METH1.
    METHODS: METH0 REDEFINITION.
  PROTECTED SECTION.
    METHODS: METH2.
  PRIVATE SECTION.
    METHODS: METH3.
ENDCLASS.                    "CLS1 DEFINITION

CLASS CLS1 IMPLEMENTATION.
  METHOD METH1.
    WRITE : / 'OK - in public'.
  ENDMETHOD.                                                "METH1

  METHOD METH2.
    WRITE : / 'OK - in protected'.
  ENDMETHOD.                                                "METH2

  METHOD METH3.
    WRITE : / 'OK -  in private'.
  ENDMETHOD.                                                "METH3

  METHOD METH0.
      WRITE : / 'OK -  From abstract'.
    ENDMETHOD.
ENDCLASS.                    "CLS1 IMPLEMENTATION


class CLS2 DEFINITION INHERITING FROM CLS1.
  PUBLIC SECTION.
    METHODS: METH4.
    METHODS: METH1 REDEFINITION.
ENDCLASS.

CLASS CLS2 IMPLEMENTATION.
    METHOD METH4.
        WRITE : / 'OK - in class2 public'.
    ENDMETHOD.

    METHOD METH1.
      WRITE : / 'OK - in class2 public - Redefine meth1 of class1'.
      CALL METHOD SUPER->METH1.
    ENDMETHOD.
ENDCLASS.

START-OF-SELECTION.

  DATA : OBJ1 TYPE REF TO CLS2.
  CREATE OBJECT OBJ1.
  CALL METHOD OBJ1->METH1.
  CALL METHOD OBJ1->METH4.
  CALL METHOD OBJ1->METH0.

 

 

7.Friend-Definition

 

REPORT ZAVI_LOGIC.

class CLS2 DEFINITION DEFERRED.

CLASS CLS1 DEFINITION FRIENDS CLS2.
  PRIVATE SECTION.
    METHODS: METH1.
ENDCLASS.                    "CLS1 DEFINITION

CLASS CLS1 IMPLEMENTATION.
  METHOD METH1.
    WRITE : / 'OK - in private'.
  ENDMETHOD.                                                "METH1
ENDCLASS.                    "CLS1 IMPLEMENTATION

class CLS2 DEFINITION INHERITING FROM CLS1.
  PUBLIC SECTION.
    METHODS: METH2.
  ENDCLASS.

CLASS CLS2 IMPLEMENTATION.
    METHOD METH2.
        WRITE : / 'OK - in class2 private'.

        DATA : OBFN TYPE REF TO CLS1.
        CREATE OBJECT OBFN.
        CALL METHOD OBFN->METH1.
    ENDMETHOD.
ENDCLASS.

START-OF-SELECTION.

  DATA : OBJ1 TYPE REF TO CLS2.
  CREATE OBJECT OBJ1.
  CALL METHOD OBJ1->METH2.

 

 

8.Event

 

REPORT ZAVI_LOGIC.

CLASS CLS1 DEFINITION .

  PUBLIC SECTION.
    EVENTS: EVT1.
    METHODS: METH1.
    METHODS : METH2 FOR EVENT EVT1 OF CLS1.

ENDCLASS.                    "CLS1 DEFINITION

CLASS CLS1 IMPLEMENTATION.
  METHOD METH1.
    WRITE : / 'OK - in PUBLIC'.

    RAISE EVENT EVT1.
  ENDMETHOD.                                                "METH1

  METHOD METH2.
    WRITE : / 'OK - CALLED VIA EVENT'.
    ENDMETHOD.
ENDCLASS.                    "CLS1 IMPLEMENTATION

START-OF-SELECTION.

  DATA : OBJ1 TYPE REF TO CLS1.
  CREATE OBJECT OBJ1.
  SET HANDLER OBJ1->METH2 FOR OBJ1.
  CALL METHOD OBJ1->METH1.

 

 

9.Interface

 

REPORT ZAVI_LOGIC.

INTERFACE INTF1.
  METHODS : METH_INTF1,METH_INTF2.
ENDINTERFACE.                                               "INTF1

CLASS CLS1 DEFINITION .
  PUBLIC SECTION.
    INTERFACES INTF1.
ENDCLASS.                    "CLS1 DEFINITION

CLASS CLS1 IMPLEMENTATION.
  METHOD INTF1~METH_INTF1.
    WRITE : / ' INSIDE CLASS 1 INTERFACE METHOD1'.
  ENDMETHOD.                    "INTF1~METH_INTF1

  METHOD INTF1~METH_INTF2.
    WRITE : / ' INSIDE CLASS 1 INTERFACE METHOD2'.
  ENDMETHOD.                    "INTF1~METH_INTF2

ENDCLASS.                    "CLS1 IMPLEMENTATION

CLASS CLS2 DEFINITION.
  PUBLIC SECTION.
    INTERFACES INTF1.
ENDCLASS.                    "CLS2 DEFINITION

CLASS CLS2 IMPLEMENTATION.
  METHOD INTF1~METH_INTF1.
    WRITE : / ' INSIDE CLASS 2 INTERFACE METHOD1'.
  ENDMETHOD.                    "INTF1~METH_INTF1

  METHOD INTF1~METH_INTF2.
    WRITE : / ' INSIDE CLASS 2 INTERFACE METHOD2'.
  ENDMETHOD.                    "INTF1~METH_INTF2
ENDCLASS.                    "CLS2 IMPLEMENTATION


START-OF-SELECTION.
  DATA : OBJ1 TYPE REF TO CLS1.
  CREATE OBJECT OBJ1.
  CALL METHOD OBJ1->INTF1~METH_INTF1.
  CALL METHOD OBJ1->INTF1~METH_INTF2.

  DATA : OBJ2 TYPE REF TO CLS2.
  CREATE OBJECT OBJ2.
  CALL METHOD OBJ2->INTF1~METH_INTF1.
  CALL METHOD OBJ2->INTF1~METH_INTF2.

 

 

10.Exception

 

REPORT ZAVI_LOGIC.

CLASS CLS1 DEFINITION .
  PUBLIC SECTION.
    METHODS METH1.
ENDCLASS.                    "CLS1 DEFINITION

CLASS CLS1 IMPLEMENTATION.
  METHOD METH1.
    DATA : LR_EX TYPE REF TO CX_ROOT.
    DATA : VAL1 TYPE I VALUE 10 ,
          VAL2 TYPE I VALUE 0,
          VAL3 TYPE I.

    DATA : PRG_NAM TYPE SYREPID,
           INCL TYPE SYREPID,
           SRC_LIN TYPE I,
           GTEXT TYPE STRING,
           GTLTX TYPE STRING.
    TRY.
        VAL3 = VAL1 / VAL2.
      CATCH CX_ROOT INTO LR_EX.
        CALL METHOD LR_EX->GET_SOURCE_POSITION
          IMPORTING
            PROGRAM_NAME = PRG_NAM
            INCLUDE_NAME = INCL
            SOURCE_LINE  = SRC_LIN.

        CALL METHOD LR_EX->IF_MESSAGE~GET_TEXT
          RECEIVING
            RESULT = GTEXT.
        CALL METHOD LR_EX->IF_MESSAGE~GET_LONGTEXT
          RECEIVING
            RESULT = GTLTX.

        WRITE : / 'Program Name : ',PRG_NAM.
        WRITE : / 'Include Name : ',INCL.
        WRITE : / 'Error Line No: ',SRC_LIN.
        WRITE : / 'Description: ',GTEXT.
        WRITE : / 'Long Text: ',GTLTX.

    ENDTRY.
  ENDMETHOD.                                                "METH1
ENDCLASS.                    "CLS1 IMPLEMENTATION

START-OF-SELECTION.

  DATA : OBJ1 TYPE REF TO CLS1.
  CREATE OBJECT OBJ1.
  CALL METHOD OBJ1->METH1.

 

 

11.Test class / Test methods

*How to execute this type of test: from menu path Program->Test->Unit Test.

 

REPORT ZAVI_LOGIC.

CLASS CLS1 DEFINITION .
  PUBLIC SECTION.
    METHODS METH1.
ENDCLASS.                    "CLS1 DEFINITION

CLASS CLS1 IMPLEMENTATION.
  METHOD METH1.
    DATA : LR_EX TYPE REF TO CX_ROOT.
    DATA : VAL1 TYPE I VALUE 10 ,
           VAL2 TYPE I VALUE 0,
           VAL3 TYPE I.

    DATA : PRG_NAM TYPE SYREPID,
           INCL TYPE SYREPID,
           SRC_LIN TYPE I,
           GTEXT TYPE STRING,
           GTLTX TYPE STRING.
    TRY.
        VAL3 = VAL1 / VAL2.
      CATCH CX_ROOT INTO LR_EX.
        RAISE EXCEPTION LR_EX.
        CALL METHOD LR_EX->GET_SOURCE_POSITION
          IMPORTING
            PROGRAM_NAME = PRG_NAM
            INCLUDE_NAME = INCL
            SOURCE_LINE  = SRC_LIN.
        CALL METHOD LR_EX->IF_MESSAGE~GET_TEXT
          RECEIVING
            RESULT = GTEXT.
        CALL METHOD LR_EX->IF_MESSAGE~GET_LONGTEXT
          RECEIVING
            RESULT = GTLTX.
        WRITE : / 'Program Name : ',PRG_NAM.
        WRITE : / 'Include Name : ',INCL.
        WRITE : / 'Error Line No: ',SRC_LIN.
        WRITE : / 'Description: ',GTEXT.
        WRITE : / 'Long Text: ',GTLTX.
    ENDTRY.
  ENDMETHOD.                                                "METH1
ENDCLASS.                    "CLS1 IMPLEMENTATION

CLASS TST1 DEFINITION "#AU Duration Short
     FOR TESTING.     "#AU Risk_Level Harmless
  PUBLIC SECTION.
    METHODS TST FOR TESTING.

ENDCLASS.                    "TST1 DEFINITION

CLASS TST1 IMPLEMENTATION.
  METHOD TST.
    DATA : OBJ1 TYPE REF TO CLS1.
    CREATE OBJECT OBJ1.
    CALL METHOD OBJ1->METH1.
  ENDMETHOD.                    "TST
ENDCLASS.                    "TST1 IMPLEMENTATION

 

 

12.Object parameters - Part 1

 

REPORT ZAVI_LOGIC.

class cls1 DEFINITION.
    PUBLIC SECTION.
        methods ADDITION 
          IMPORTING VALUE(V1) TYPE I VALUE(V2) TYPE I RETURNING VALUE(R1) TYPE I.
        methods DIVISION 
          IMPORTING VALUE(V1) TYPE I VALUE(V2) TYPE I RETURNING VALUE(R1) TYPE I.
        methods MULTIPLI 
          IMPORTING VALUE(V1) TYPE I VALUE(V2) TYPE I RETURNING VALUE(R1) TYPE I.
        methods SUBSTRAC 
          IMPORTING VALUE(V1) TYPE I VALUE(V2) TYPE I RETURNING VALUE(R1) TYPE I.

     PRIVATE SECTION.
        DATA : ANS TYPE I.
  endclass.

class cls1 IMPLEMENTATION.

    method ADDITION.
      CLEAR ans.
      ANS = V1 + V2.
      R1 = ANS.
    ENDMETHOD.

    method DIVISION.
      CLEAR ans.
      ANS = V1 / V2.
      R1 = ANS.
    ENDMETHOD.

    method MULTIPLI.
      CLEAR ans.
      ANS = V1 * V2.
      R1 = ANS.
    ENDMETHOD.

    method SUBSTRAC.
      CLEAR ans.
      ANS = V1 - V2.
      R1 = ANS.
    ENDMETHOD.

ENDCLASS.



  START-OF-SELECTION.
  DATA : ANS TYPE I.
  DATA : OBJ1 TYPE REF TO CLS1.
  CREATE OBJECT OBJ1.

  CALL METHOD OBJ1->ADDITION EXPORTING V1 = 10 V2 = 20 RECEIVING R1 = ANS.
  WRITE : / 'Addition is: ',ans.

  CALL METHOD OBJ1->DIVISION EXPORTING V1 = 10 V2 = 20 RECEIVING R1 = ANS.
  WRITE : / 'Division is: ',ans.

  CALL METHOD OBJ1->MULTIPLI EXPORTING V1 = 10 V2 = 20 RECEIVING R1 = ANS.
  WRITE : / 'Multiplication is: ',ans.

  CALL METHOD OBJ1->SUBSTRAC EXPORTING V1 = 10 V2 = 20 RECEIVING R1 = ANS.
  WRITE : / 'Substraction is: ',ans.

 

 

13.Object parameters - Part 2 (Exception and Raising)

A. Raising->Automatic error handling.

 

REPORT ZAVI_LOGIC.

class cls1 DEFINITION.
    PUBLIC SECTION.
        methods DIVISION
          IMPORTING VALUE(V1) TYPE I VALUE(V2) TYPE I
            RETURNING VALUE(R1) TYPE I RAISING cx_sy_arithmetic_error.

     PRIVATE SECTION.
        DATA : ANS TYPE I.
  endclass.

class cls1 IMPLEMENTATION.
    method DIVISION.
      CLEAR ans.
      ANS = V1 / V2.
      R1 = ANS.
    ENDMETHOD.

ENDCLASS.


  START-OF-SELECTION.
  DATA : ANS TYPE I.
  data : err type ref to cx_sy_arithmetic_error.
  data : txt type string.
  DATA : OBJ1 TYPE REF TO CLS1.
  CREATE OBJECT OBJ1.

  try.
  CALL METHOD OBJ1->DIVISION EXPORTING V1 = 10 V2 = 0 RECEIVING R1 = ANS.
  catch cx_sy_arithmetic_error INTO err.
      txt = err->get_text( ).
  endtry.

  WRITE : / 'Division is: ',ans.
  WRITE : / 'Error is : ',txt.

 

 

B. Exception->manually error code assign and handle.

 

class cls1 DEFINITION.
    PUBLIC SECTION.
        methods DIVISION
          IMPORTING VALUE(V1) TYPE I VALUE(V2) TYPE I
            RETURNING VALUE(R1) TYPE I EXCEPTIONS err.

     PRIVATE SECTION.
        DATA : ANS TYPE I.
  endclass.

class cls1 IMPLEMENTATION.
    method DIVISION.
      CLEAR ans.
      try.
      ANS = V1 / V2.
      catch cx_sy_arithmetic_error.
          RAISE ERR.
      ENDTRY.
      R1 = ANS.
    ENDMETHOD.
ENDCLASS.

START-OF-SELECTION.
  DATA : ANS TYPE I.
  data : err type ref to cx_sy_arithmetic_error.
  data : txt type string.
  DATA : OBJ1 TYPE REF TO CLS1.
  CREATE OBJECT OBJ1.

  CALL METHOD OBJ1->DIVISION
  EXPORTING V1 = 10 V2 = 0 RECEIVING R1 = ANS EXCEPTIONS ERR = 11.

IF SY-SUBRC EQ 0.
      WRITE : ANS.
  ELSEIF SY-SUBRC EQ 11.
     WRITE : / 'Divide zero error'.
    ENDIF.

 

 

14.MVC Pattern

 

REPORT ZAVI_LOGIC.

DATA : IT TYPE TABLE OF MARA .

CLASS MODEL DEFINITION.
  PUBLIC SECTION.
    METHODS: QUERY.
ENDCLASS.

CLASS MODEL IMPLEMENTATION.
    METHOD QUERY.
      SELECT * FROM MARA INTO TABLE IT UP TO 50 ROWS.
    ENDMETHOD.
ENDCLASS.

CLASS CTRL DEFINITION.
  PUBLIC SECTION.
    DATA : MODEL TYPE REF TO MODEL.
    METHODS: CONSTRUCTOR,
             DSP_REPORT.
    PRIVATE SECTION.
      DATA : GRID TYPE REF TO CL_SALV_TABLE.
      METHODS: SHOW_GRID.
ENDCLASS.

CLASS CTRL IMPLEMENTATION.
  METHOD CONSTRUCTOR.
    CREATE OBJECT MODEL.
  ENDMETHOD.

  METHOD DSP_REPORT.
      CALL METHOD MODEL->QUERY.
      SHOW_GRID( ).
  ENDMETHOD.

  METHOD SHOW_GRID.
      CL_SALV_TABLE=>FACTORY( IMPORTING R_SALV_TABLE = GRID CHANGING T_TABLE = IT ).
      GRID->DISPLAY( ).
  ENDMETHOD.
ENDCLASS.

START-OF-SELECTION.
DATA : LR_CTRL TYPE REF TO CTRL.
CREATE OBJECT LR_CTRL.
CALL METHOD LR_CTRL->DSP_REPORT.

 



 

Author: Chetanpal Singh
Submitted: December 14, 2006

As the number of calls to programs (or class-methods) that raise class-based exceptions increases, so can (highly likely) be the code to handle the exceptions expected from the called programs. This article presents an approach and utility to simplify capturing, evaluating and communicating class-based exceptions.

 Simplifying the Capturing, Evaluating, and Communicating Class-Based Except

Error rendering macro 'code': Invalid value specified for parameter 'com.atlassian.confluence.ext.code.render.InvalidValueException'
REPORT  yclasses   LINE-SIZE 120.

*----------------------------------------------------------------------*
*       CLASS parentclass DEFINITION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS parentclass DEFINITION .
  PUBLIC SECTION.
    DATA : commondata(30) TYPE c VALUE 'Accessible to all'.
    METHODS : showval.
  PROTECTED SECTION.
    DATA : protectdata(40) TYPE c VALUE 'Protected data'.
  PRIVATE SECTION.
    DATA : privatedata(30) TYPE c VALUE 'Private data'.
ENDCLASS.                    "parentclass DEFINITION
*----------------------------------------------------------------------*
*       CLASS parentclass IMPLEMENTATION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS parentclass IMPLEMENTATION.
  METHOD : showval.
    WRITE:/5 'All data from parentclass shown:-'.
    WRITE:/ sy-uline.
    WRITE:/5 commondata,
          /5 protectdata,
          /5 privatedata.
  ENDMETHOD.                    ":
ENDCLASS.                    "parentclass IMPLEMENTATION
*----------------------------------------------------------------------*
*       CLASS childclass DEFINITION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS childclass DEFINITION INHERITING FROM parentclass.
  PUBLIC SECTION .
    METHODS : subval.
ENDCLASS.                    "childclass DEFINITION
*----------------------------------------------------------------------*
*       CLASS childclass IMPLEMENTATION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS childclass IMPLEMENTATION.
  METHOD : subval.
    SKIP 1.
    WRITE:/5 'Data of parent shown from child-'.
    WRITE:/5 sy-uline.
    WRITE:/5 commondata,
          /5 protectdata.
    commondata = 'Public data changed in subclass'.
    protectdata = 'Protected data changed in subclass'.
    WRITE:/5 sy-uline.
    WRITE:/5 commondata,
          /5 protectdata.
  ENDMETHOD.                    ":
ENDCLASS.                    "childclass IMPLEMENTATION

START-OF-SELECTION.

  DATA : parent TYPE REF TO parentclass ,
        child TYPE REF TO childclass .
  CREATE OBJECT : parent ,
                  child .
  CALL METHOD : parent->showval ,
                child->subval.
  SKIP 2.
  parent->commondata = 'User changing public data'.
  WRITE:/5 parent->commondata.

Create a Class dynamically by passing class name at run time:

CREATE OBJECT

CREATE OBJECT oref
   TYPE class|(name)
    parameter list.

... PARAMETER-TABLE ptab

... EXCEPTION-TABLE etab

Effect

We can use these additions when the instanced class is specified dynamically in name. You use the special internal tables ptab and etab to assign actual parameters to the input parameters of the instance constructor or return values to not class-based exceptions.
The internal tables ptab and etab must be defined with reference to the tables ABAP_PARMBIND_TAB and ABAP_EXCPBIND_TAB.
Sample program where the class name is passed as variable and the exporting parameter is passed in Parameter-table.

REPORT z_dyn_classname.

CLASS cl_abap_objectdescr DEFINITION LOAD.
DATA: container TYPE REF TO object,
      pic_container TYPE REF TO cl_gui_container,
      exc_ref TYPE REF TO cx_root,
      lo_cast_error TYPE REF TO cx_sy_move_cast_error,
      exc_text TYPE string.
* Picture Control
DATA picture TYPE REF TO cl_gui_picture.

DATA: class TYPE string VALUE 'CL_GUI_DIALOGBOX_CONTAINER',
      ptab TYPE abap_parmbind_tab,
      ptab_line TYPE abap_parmbind.

CALL SCREEN 100.

*----------------------------------------------------------------------*
*  MODULE STATUS_0100 OUTPUT
*----------------------------------------------------------------------*
MODULE status_0100 OUTPUT.

  ptab_line-name = 'WIDTH'.
  ptab_line-kind = cl_abap_objectdescr=>exporting.
  GET REFERENCE OF 1000 INTO ptab_line-value.
  INSERT ptab_line INTO TABLE ptab.

  ptab_line-name = 'PARENT'.
  ptab_line-kind = cl_abap_objectdescr=>exporting.
  GET REFERENCE OF cl_gui_container=>desktop
                INTO ptab_line-value.
  INSERT ptab_line INTO TABLE ptab.

  ptab_line-name = 'HEIGHT'.
  ptab_line-kind = cl_abap_objectdescr=>exporting.
  GET REFERENCE OF 300 INTO ptab_line-value.
  INSERT ptab_line INTO TABLE ptab.

  TRY.
      CREATE OBJECT container TYPE (class)
        PARAMETER-TABLE ptab.
    CATCH cx_sy_create_object_error INTO exc_ref.
      exc_text = exc_ref->get_text( ).
      MESSAGE exc_text TYPE 'I'.
  ENDTRY.
  TRY.
* Now, the Widening cast to move the reference from the
* generic object to dialogbox parent container class (more specific class).
      pic_container ?= container.
    CATCH cx_sy_move_cast_error INTO lo_cast_error.
      WRITE: / 'Widening cast failed'.
  ENDTRY.

  CREATE OBJECT picture
    EXPORTING
      parent = pic_container.

* Request an URL from the data provider by exporting the pic_data.
  DATA url(255).
  CLEAR url.
  PERFORM load_pic_from_db CHANGING url.

* load picture
  CALL METHOD picture->load_picture_from_url
    EXPORTING
      url = url.

  CALL METHOD cl_gui_cfw=>flush
    EXCEPTIONS
      cntl_system_error = 1
      cntl_error        = 2.
  IF sy-subrc <> 0.
* error handling
  ENDIF.
ENDMODULE.                    "STATUS_0100 OUTPUT
*&---------------------------------------------------------------------*
*&      Form  load_pic_from_db
*&---------------------------------------------------------------------*
FORM load_pic_from_db CHANGING url.
  DATA query_table LIKE w3query OCCURS 1 WITH HEADER LINE.
  DATA html_table LIKE w3html OCCURS 1.
  DATA return_code LIKE w3param-ret_code.
  DATA content_type LIKE  w3param-cont_type.
  DATA content_length LIKE  w3param-cont_len.
  DATA pic_data LIKE w3mime OCCURS 0.
  DATA pic_size TYPE i.

  REFRESH query_table.
  query_table-name = '_OBJECT_ID'.
  query_table-value = 'ENJOYSAP_LOGO'.
  APPEND query_table.

  CALL FUNCTION 'WWW_GET_MIME_OBJECT'
    TABLES
      query_string        = query_table
      html                = html_table
      mime                = pic_data
    CHANGING
      return_code         = return_code
      content_type        = content_type
      content_length      = content_length
    EXCEPTIONS
      object_not_found    = 1
      parameter_not_found = 2
      OTHERS              = 3.
  IF sy-subrc = 0.
    pic_size = content_length.
  ENDIF.

  CALL FUNCTION 'DP_CREATE_URL'
    EXPORTING
      type     = 'image'
      subtype  = cndp_sap_tab_unknown
      size     = pic_size
      lifetime = cndp_lifetime_transaction
    TABLES
      data     = pic_data
    CHANGING
      url      = url
    EXCEPTIONS
      OTHERS   = 1.

ENDFORM.                    "load_pic_from_db
 
*&---------------------------------------------------------------------*
*& Report  Y_MY_CASE_STUDY                                     *
*&                                                                     *
*&---------------------------------------------------------------------*
*& Simple example for handling events in Object Oriented Technique     *                                                                *
*& using buyer and seller scenario                                     *
*&---------------------------------------------------------------------*
REPORT  y_my_case_study                 .
*---------------------------------------------------------------------*
*       Global Data
*---------------------------------------------------------------------*
DATA: t_stock TYPE c LENGTH 6,   " Total Availabale Stock- Screen Field
      ok_code TYPE sy-ucomm.     " Contains Function Code
*---------------------------------------------------------------------*
*       CLASS storage_location DEFINITION
*---------------------------------------------------------------------*
* This class represents storage location
*---------------------------------------------------------------------*
CLASS storage_location DEFINITION.
  PUBLIC SECTION.
    METHODS: display.                      " Method to display available stock
    EVENTS : threshold,                    " Event to warn when threshold value of stock reached
             max,                          " Event to warn when maximum value of stock reached
             no_stock.                     " Event to warn when stock is zero
  PROTECTED SECTION.
    CLASS-DATA : w_stock TYPE i VALUE 0.   " Available stock
    DATA : w_max TYPE i VALUE 10,          " Maximum capacity of storage location
           w_threshold TYPE i VALUE 8.     " Threshold Value of stock
ENDCLASS.                    "storage_location DEFINITION
*---------------------------------------------------------------------*
*       CLASS storage_location IMPLEMENTATION
*---------------------------------------------------------------------*
* Implementation of storage_location class
*---------------------------------------------------------------------*
CLASS storage_location IMPLEMENTATION.
  METHOD display.
    WRITE : / 'Available Stock : ', w_stock.
  ENDMETHOD.                               "display
ENDCLASS.                    "storage_location IMPLEMENTATION
*---------------------------------------------------------------------*
*       CLASS sales DEFINITION
*---------------------------------------------------------------------*
* Seller class, class responsible for selling the available stock
*---------------------------------------------------------------------*
CLASS sales DEFINITION INHERITING FROM storage_location.
  PUBLIC SECTION.
    METHODS: sell_the_product.              " Method responsible for selling the stock
ENDCLASS.                    "sales DEFINITION
*---------------------------------------------------------------------*
*       CLASS sales IMPLEMENTATION
*---------------------------------------------------------------------*
* Seller class implementation
*---------------------------------------------------------------------*
CLASS sales IMPLEMENTATION.
  METHOD sell_the_product.
    IF w_stock = 0.                         " Raise Event no_stock when stock is zero
      RAISE EVENT no_stock.
    ELSE.
      w_stock = w_stock - 1.                " Else decrement the available stock
      t_stock = w_stock.
    ENDIF.
  ENDMETHOD.                    "sale_the_product
ENDCLASS.                    "sales IMPLEMENTATION
*---------------------------------------------------------------------*
*       CLASS buying DEFINITION
*---------------------------------------------------------------------*
* Buyer class, class responsible for buying the stock
*---------------------------------------------------------------------*
CLASS buying DEFINITION INHERITING FROM storage_location.
  PUBLIC SECTION.
    METHODS: buy_the_product.               " Buys the stock
ENDCLASS.                    "buying DEFINITION
*---------------------------------------------------------------------*
*       CLASS buying IMPLEMENTATION
*---------------------------------------------------------------------*
* Buyer class implementation
*---------------------------------------------------------------------*
CLASS buying IMPLEMENTATION.
  METHOD buy_the_product.
    IF w_stock = w_max.                    " Raises event max when stock is maximum
      RAISE EVENT max.
    ELSE.
      IF w_stock GE w_threshold.           " Raises event threshold when stock reaches nearer to maximum
        RAISE EVENT threshold.             " example if max is 10 then it raises when stock reaches 8
      ENDIF.
      w_stock = w_stock + 1.               " Else buy the stock
      t_stock = w_stock.
    ENDIF.
  ENDMETHOD.                    "buy_the_product
ENDCLASS.                    "buying IMPLEMENTATION
*---------------------------------------------------------------------*
*       CLASS event_handler DEFINITION
*---------------------------------------------------------------------*
* Class to handle the events no_stock, threshold and max.
*---------------------------------------------------------------------*
CLASS event_handler DEFINITION.
  PUBLIC SECTION.
    METHODS : max_handler FOR EVENT max OF storage_location,
              threshold_handler FOR EVENT threshold OF storage_location,
              no_stock_handler FOR EVENT no_stock OF storage_location.
ENDCLASS.                    "event_handler DEFINITION
*---------------------------------------------------------------------*
*       CLASS event_handler IMPLEMENTATION
*---------------------------------------------------------------------*
* Event-handler class implementation
*---------------------------------------------------------------------*
CLASS event_handler IMPLEMENTATION.
  METHOD max_handler.
    MESSAGE 'Stop buying the product, No space at storage location' TYPE 'I'.
  ENDMETHOD.                    "max_handler
  METHOD threshold_handler.
    MESSAGE 'Threshold Value Reached, Check storage space before next buying' TYPE 'I'.
  ENDMETHOD.                    "threshold_handler
  METHOD no_stock_handler.
    MESSAGE 'No product available for sale. Buy the product to sell' TYPE 'I'.
  ENDMETHOD.                    "no_stock_handler
ENDCLASS.                    "event_handler IMPLEMENTATION
*---------------------------------------------------------------------*
*       START-OF-SELECTION
*---------------------------------------------------------------------*
START-OF-SELECTION.
  DATA : buyer TYPE REF TO buying,               " Buyer Object
         seller TYPE REF TO sales,               " Seller object
         ehandler TYPE REF TO event_handler.     " Event handler object
  CREATE OBJECT : buyer,                         " Creation of all the above mentioned objects
                  seller,
                  ehandler.
  SET HANDLER ehandler->max_handler              " Assignes all event handler methods to
              ehandler->threshold_handler        " event handler object
              ehandler->no_stock_handler
              FOR ALL INSTANCES.
**** Initial screen **********
  CALL SCREEN 500.
*&---------------------------------------------------------------------*
*&      Module  STATUS_0500  OUTPUT
*&---------------------------------------------------------------------*
* Status module of screen 500
*----------------------------------------------------------------------*
MODULE status_0500 OUTPUT.
*---------------------------------------------------------------------*
* sets status with 3 buttons on application toolbar, 1- Buyer 2- Seller
* 3- Exit
*---------------------------------------------------------------------*
  SET PF-STATUS 'Ys_MYCASESTUDY'.
  SET TITLEBAR '001'.                       " Title - Buyer Seller Problem
ENDMODULE.                 " STATUS_0500  OUTPUT
*&---------------------------------------------------------------------*
*&      Module  USER_COMMAND_0500  INPUT
*&---------------------------------------------------------------------*
* This module is used to handle all user-commands
*----------------------------------------------------------------------*
MODULE user_command_0500 INPUT.
  CASE ok_code.
    WHEN 'BUYER'.                               " When Buyer Button is pressed
      CALL METHOD buyer->buy_the_product.
    WHEN 'SELLER'.                              " When Seller Button is pressed
      CALL METHOD seller->sell_the_product.
    WHEN 'EXIT'.                                " When Exit Button is pressed
      LEAVE PROGRAM.
  ENDCASE.
ENDMODULE.                 " USER_COMMAND_0500  INPUT
 

Author:  Timo John ( cimt-ag )
Submitted:        2010-04-14
Related Links:

In other development tools like Eclipse it is pretty standard that you are able to generate all GET and SET methodsfor your classes.
I decided to write a Report program that does the generation of GET and SET methods for you (source code below)

The  report will ask you for class in the Selection Screen. While running it,
all attributes are analysed and the Methods are created and activated right away.

Aditionaly there are 2 other programms needed: Report Z_SRCGEN_GET_SET  and Include Z_TMPL_GET_SET which are also listed below. 

TO-DO (for me):
1. Option to delete old GET / SET Methods
2. Get rid of German in the Code

The program is new, so I look forward for your hints or improvements. 
Kind Regards.

Timo John


Z_TJ_GENARATE_GET_SET

Error rendering macro 'code': Invalid value specified for parameter 'com.atlassian.confluence.ext.code.render.InvalidValueException'
*&---------------------------------------------------------------------*
*& Report  Z_TJ_GENARATE_GET_SET
*&
*&---------------------------------------------------------------------*
*& Author:  Timo John
*& Contact: Timo.John@cimt-ag.de
*&
*& Program to gernerate GET and SET Methods for ABAP Object Classes.
*&
*& State: Early Beta. !!!
*&
*& This report directly generates GET and SET Methods for all attributes
*& in the selected Class.
*&
*& Methods that exist are not touched.
*&
*&  Precondition:
*&    1. The Attributes have to follow a naming convention starting
*&       with "XX_" like gf_myGlobalField
*&
*&
*&  TO-DO:
*&    1. Enable option to delete old methods there the attribute is gone.
*&
*&
*&---------------------------------------------------------------------*
REPORT  z_tj_genarate_get_set.

TYPE-POOLS: seoo,
            ostyp.

DATA:     gf_count          TYPE i,
          lf_method_name    TYPE string,
          gf_mtdname        TYPE seocpdname,
          gf_classname      TYPE seoclskey,
          ls_method         TYPE seoo_method_r,
          lt_parameters     TYPE seos_parameters_r,
          ls_parameters     TYPE seos_parameter_r,
          lt_exceptions     TYPE seos_exceptions_r,
          gt_attributes     TYPE seoo_attributes_r,
          ls_attributes     LIKE LINE OF gt_attributes.

DATA:     ls_meth_key           TYPE seocpdkey,
          gt_impl_data          TYPE abap_parmbind_tab,
          ls_data               LIKE LINE OF gt_impl_data,
          gf_attribute          TYPE objname.

DATA:   gf_temlate TYPE schemename,
        gc_templ_prog TYPE schemeprog VALUE 'Z_TMPL_GET_SET',
        gc_build TYPE ostyp_build VALUE '000001'.

DATA: gi_orsal       TYPE REF TO cl_osral_oo,
      gi_naming      TYPE REF TO if_oo_class_incl_naming.


SELECTION-SCREEN BEGIN OF BLOCK b01 WITH FRAME TITLE text-b01.
PARAMETERS: so_clnam TYPE seoclass-clsname MEMORY ID class MATCHCODE OBJECT sfbeclname.
SELECTION-SCREEN END OF BLOCK b01.


* Map Parameter of Classname
gf_classname =  so_clnam.

* Setup:
gi_naming ?= cl_oo_include_naming=>get_instance_by_name( so_clnam ).


* Start Generation class
gi_orsal = cl_osral_oo=>get_repository_obj( gf_classname ).
gi_orsal->set_generator('Z_SRCGEN_GET_SET').

* Get information about Class
CALL FUNCTION 'SEO_CLASS_TYPEINFO_GET'
  EXPORTING
    clskey     = gf_classname
  IMPORTING
    attributes = gt_attributes
  EXCEPTIONS
    OTHERS     = 1.

* Set common data for all methods:
ls_method-clsname           = gf_classname.
ls_parameters-clsname       = gf_classname.
ls_method-state             = seoc_state_implemented. "1.

*  for implementation
ls_meth_key-clsname = gf_classname.

LOOP AT gt_attributes INTO ls_attributes.

* Data for both Methods:
*  for parameters
  ls_parameters-typtype       = ls_attributes-typtype.  " Type of parametery type type, like ref to etc ...)
  ls_parameters-sconame       = ls_attributes-cmpname.  "name of current attribut
  TRANSLATE ls_parameters-sconame TO LOWER CASE.

  IF ls_attributes-cmpname+2(1) = '_'.
    lf_method_name = ls_attributes-cmpname+3.
  ELSE.
    lf_method_name = ls_attributes-cmpname.
  ENDIF.

** SET defintion *****************************
* check if method exists
  CONCATENATE 'SET_' lf_method_name INTO ls_method-cmpname.
  gf_mtdname = ls_method-cmpname.
  CALL METHOD gi_naming->get_include_by_mtdname
    EXPORTING
      mtdname = gf_mtdname
    EXCEPTIONS
      OTHERS  = 1.
  IF sy-subrc <> 0 .

    ls_method-exposure = seoc_exposure_public. "2.

* Parameters for SET
    ls_parameters-cmpname       = ls_method-cmpname.
    ls_parameters-sconame(1)  = 'i'.
    ls_parameters-type        = ls_attributes-type.
    ls_parameters-pardecltyp  = seos_pardecltyp_importing.
    APPEND ls_parameters TO lt_parameters.

* Create method SET
    gi_orsal->method_def_modify( i_method     = ls_method
                                 i_parameters = lt_parameters
                                 i_exceptions = lt_exceptions ).

**********************************************************************
* Create method implementation SET.
    ls_meth_key-cpdname = ls_method-cmpname.

    ls_data-name   =  'CLASS_NAME'.
    GET REFERENCE OF gf_classname INTO ls_data-value.
    INSERT ls_data INTO TABLE gt_impl_data.

    ls_data-name   =  'SOURCE'.
    GET REFERENCE OF gc_templ_prog INTO ls_data-value.
    INSERT ls_data INTO TABLE gt_impl_data.

    ls_data-name   =  'BUILD'.
    GET REFERENCE OF gc_build INTO ls_data-value.
    INSERT ls_data INTO TABLE gt_impl_data.

    gf_temlate = 'PM_SET_METHOD'.
    ls_data-name   =  'TEMPLATE'.
    GET REFERENCE OF gf_temlate INTO ls_data-value.
    INSERT ls_data INTO TABLE gt_impl_data.

    ls_data-name   =  'IMPORTING_VAR'.
    GET REFERENCE OF ls_parameters-sconame INTO ls_data-value.
    INSERT ls_data INTO TABLE gt_impl_data.

    gf_attribute = ls_attributes-cmpname.
    ls_data-name   =  'ATTRIBUTE'.
    GET REFERENCE OF gf_attribute INTO ls_data-value.
    INSERT ls_data INTO TABLE gt_impl_data.

    gi_orsal->method_imp_create( i_method    = ls_meth_key
                                 i_data      = gt_impl_data ).
    gf_count = gf_count + 1.
  ENDIF.

    CLEAR: gt_impl_data,
           lt_parameters.

**********************************************************************
** GET defintion

  CONCATENATE 'GET_' ls_attributes-cmpname+3 INTO ls_method-cmpname.
* check if method exist: IF than skip creation
  gf_mtdname = ls_method-cmpname.
  CALL METHOD gi_naming->get_include_by_mtdname
    EXPORTING
      mtdname = gf_mtdname
    EXCEPTIONS
      OTHERS  = 1.
  IF sy-subrc <> 0.
*   parameters for GET
    ls_parameters-cmpname     = ls_method-cmpname.
    ls_parameters-sconame(1)  = 'r'.
    ls_parameters-pardecltyp  = seos_pardecltyp_returning .
    APPEND ls_parameters TO lt_parameters.

*   create method
    gi_orsal->method_def_modify( i_method     = ls_method
                                 i_parameters = lt_parameters
                                 i_exceptions = lt_exceptions ).

**********************************************************************
*   getter implementatiuon
    ls_meth_key-cpdname = ls_method-cmpname.

    ls_data-name   =  'CLASS_NAME'.
    GET REFERENCE OF gf_classname INTO ls_data-value.
    INSERT ls_data INTO TABLE gt_impl_data.

    ls_data-name   =  'SOURCE'.
    GET REFERENCE OF gc_templ_prog INTO ls_data-value.
    INSERT ls_data INTO TABLE gt_impl_data.

    ls_data-name   =  'BUILD'.
    GET REFERENCE OF gc_build INTO ls_data-value.
    INSERT ls_data INTO TABLE gt_impl_data.

    gf_temlate     = 'PM_GET_METHOD'.
    ls_data-name   =  'TEMPLATE'.
    GET REFERENCE OF gf_temlate INTO ls_data-value.
    INSERT ls_data INTO TABLE gt_impl_data.

    ls_data-name   =  'RETURNING_VAR'.
    GET REFERENCE OF ls_parameters-sconame INTO ls_data-value.
    INSERT ls_data INTO TABLE gt_impl_data.

    gf_attribute = ls_attributes-cmpname.
    ls_data-name   =  'ATTRIBUTE'.
    GET REFERENCE OF gf_attribute INTO ls_data-value.
    INSERT ls_data INTO TABLE gt_impl_data.

    gi_orsal->method_imp_create( i_method    = ls_meth_key
                                 i_data      = gt_impl_data ).
**********************************************************************
    CLEAR: gt_impl_data,
          lt_parameters.

    gf_count = gf_count + 1.
  ENDIF.

ENDLOOP.

* Speichern !
gi_orsal->save( ).


MESSAGE s037(bsp_wd_tools) WITH gf_count.
*   &1 Methode(n) ist/sind generiert

Z_SRCGEN_GET_SET Generator Report

Error rendering macro 'code': Invalid value specified for parameter 'com.atlassian.confluence.ext.code.render.InvalidValueException'
*&---------------------------------------------------------------------*
*& Report  Z_SRCGEN_GET_SET                                            *
*&                                                                     *
*&---------------------------------------------------------------------*
*&                                                                     *
*&---------------------------------------------------------------------*
REPORT Z_SRCGEN_GET_SET .
TYPE-POOLS: SEOP, OSTYP, OSCON, ABAP.
** global field symbols
field-symbols:  <CLNAME>    type seoclskey, "Name der Anwendungsklasse
                <SOURCE>    type schemeprog, "Source
                <TEMPLATE>  type schemename, "Template
                <BUILD>     type OSTYP_BUILD, "BUILD
                <ATTRIBUTE> type OBJNAME,
                <ATTRIBUTE_LIST> type OSTYP_OBJNAME_TAB,
                <ATTRIBUTE_TNOUPD> type OS_BOOLEAN,
                <IMPORTING_VAR> type OBJNAME,
                <RETURNING_VAR> type OBJNAME.
** variables for scheme instantiation
types: begin of TYP_ATTRIBUTE,
         NAME type OBJNAME,
       end of TYP_ATTRIBUTE.
data: ATTRIBUTE_TAB type standard table of TYP_ATTRIBUTE
                         with header line, "#EC *
      ATTRIBUTE     type OBJNAME, "#EC NEEDED
      ATTRIBUTE_TNOUPD type OS_BOOLEAN value OSCON_FALSE, "#EC NEEDED
      ATTR_NS       type OBJNAME, "#EC NEEDED
      ATTR_NA       type OBJNAME, "#EC NEEDED
      CLASS_NAME    type seoclskey, "#EC NEEDED
      IMPORTING_VAR type OBJNAME, "#EC NEEDED
      RETURNING_VAR type OBJNAME. "#EC NEEDED
data: THISPROG  like SY-REPID.
***************  Subroutines data access  ************************
data DATA       type abap_parmbind.
form SET_DATA
  using DATA_BLOCK type ABAP_PARMBIND_TAB. "#EC CALLED
  data: FDPOS type syfdpos.
  loop at DATA_BLOCK into DATA.
    case DATA-name.
      when 'CLASS_NAME'.
        assign DATA-value->* TO <CLNAME>.
        CLASS_NAME = <CLNAME>.
      when 'SOURCE'.
        assign DATA-value->* TO <source>.
      when 'TEMPLATE'.
        assign DATA-value->* TO <template>.
      when 'BUILD'.
        assign DATA-value->* TO <build>.
      when 'ATTRIBUTE'.
        assign DATA-value->* TO <ATTRIBUTE>.
        ATTRIBUTE = <ATTRIBUTE>.
      when 'ATTRIBUTE_TNOUPD'.
        assign DATA-value->* TO <ATTRIBUTE_TNOUPD>.
        ATTRIBUTE_TNOUPD = <ATTRIBUTE_TNOUPD>.
      when 'ATTRIBUTES'.
        refresh ATTRIBUTE_TAB.
        assign DATA-value->* TO <ATTRIBUTE_LIST>.
        append lines of <ATTRIBUTE_LIST> to ATTRIBUTE_TAB.
      when 'IMPORTING_VAR'.
        assign DATA-value->* TO <IMPORTING_VAR>.
        IMPORTING_VAR = <IMPORTING_VAR>.
      when 'RETURNING_VAR'.
        assign DATA-value->* TO <RETURNING_VAR>.
        RETURNING_VAR = <RETURNING_VAR>.
    endcase. "DATA-name
  endloop. "at DATA_BLOCK
* * Namespace
  clear ATTR_NS.
  ATTR_NA = ATTRIBUTE.
  if ATTRIBUTE(1) = '/'.
    if ATTRIBUTE+1 ca '/'.
      FDPOS = SY-FDPOS + 2.
      ATTR_NS = ATTRIBUTE(FDPOS).
      ATTR_NA = ATTRIBUTE+FDPOS.
    endif.
  endif.
endform. "SET_DATA

FORM get_data
  CHANGING data_block TYPE ABAP_PARMBIND_TAB. "#EC CALLED
  data-name  = 'CLASS_NAME'.
  GET REFERENCE OF <clname> INTO data-value.
  INSERT data INTO TABLE data_block.
  data-name  = 'SOURCE'.
  GET REFERENCE OF <source> INTO data-value.
  INSERT data INTO TABLE data_block.
  data-name  = 'TEMPLATE'.
  GET REFERENCE OF <template> INTO data-value.
  INSERT data INTO TABLE data_block.
ENDFORM. "get_data

***************  Subroutine for instantiation  ************************
FORM method
  TABLES t_coding            TYPE seop_source. "#EC CALLED
  REFRESH  t_coding.
  thisprog = sy-repid.
  CALL FUNCTION 'SCHEME_INSTANTIATE'
       EXPORTING  CALLING_PROGRAM      = thisprog
                  SCHEME_PROGRAM       = <source>
                  SCHEME_NAME          = <template>
       TABLES     RESULT_TAB           = t_coding
       EXCEPTIONS SCHEMEPROG_NOT_FOUND = 1
                  SCHEME_NOT_FOUND     = 2
                  SCHEME_SYNTAX_ERROR  = 3
                  GENERATE_ERROR       = 4
                  FORCED_LINESPLIT     = 5
                  TABLE_NOT_EXISTS     = 6
                  OTHERS               = 7.
  if <build> is assigned.
    concatenate '***BUILD' <build> into t_coding separated by space.
    insert t_coding index 1.
  endif.
ENDFORM. "method

Z_TMPL_GET_SET Template Include

***INCLUDE Z_TMPL_GET_SET
***BUILD 000001
*
* Z ABAP OO Template:
* To generate Getter and Setter
*
/>PM_SET_METHOD</
* This is a generated SET Method for attribute: &ATTRIBUTE&:
  &ATTRIBUTE& = &IMPORTING_VAR&.
/>END</
/>PM_GET_METHOD</
* This is a generated GET Method for attribute: &ATTRIBUTE&:
   &RETURNING_VAR& = &ATTRIBUTE&.
/>END</

List of all pages

Pages at first level

* This program will make you clear about the usage of GET CURSOR FIELD and SET PARAMETER ID statements.

Requirement: 

Create a basic list to display orders for the given customers in the selection screen and perform the following: (Display the customer number, customer name and the order number on the basic list)
Provide two push buttons 'Customer Info' and 'Order Info' on the basic list.
Display the transaction 'Display customer' when the user places the cursor on the customer and clicks on the button 'Customer Info'. The customer number should be displayed on the initial screen of the transaction.
Display the transaction 'Display Sales order' when the user places the cursor on the order and clicks on the button 'Order Info'. The order number should be displayed on the initial screen of the transaction.
On line selection, display the order details. (Order details include: Item number, Material number, ordered quantity, and price.)

Note:

 Create a PF STATUS with two pushbuttons of function codes CUSTOMER and ORDER.

Error rendering macro 'code': Invalid value specified for parameter 'com.atlassian.confluence.ext.code.render.InvalidValueException'
REPORT ZDEMO.
*Table declaration...................................................
TABLES:
 vbak.
SELECTION-SCREEN BEGIN OF BLOCK b1 WITH FRAME TITLE text-003.
SELECT-OPTIONS:
  s_kunnr FOR vbak-kunnr.
SELECTION-SCREEN END OF BLOCK b1.
*--------------------------------------------------------------------*
*            TYPE DECLARATION TO HOLD CUSTOMER DETAILS
*--------------------------------------------------------------------*
TYPES:
 BEGIN OF type_s_cust,
  kunnr TYPE kna1-kunnr,               " Customer Number
  name1 TYPE kna1-name1,               " Customer Name
  vbeln TYPE vbak-vbeln,               " Order Number
 END OF type_s_cust,
*--------------------------------------------------------------------*
*              TYPE DECLARATION TO HOLD ORDER DETAILS
*--------------------------------------------------------------------*
 BEGIN OF type_s_order,
  posnr TYPE vbap-posnr,               " Sales Document Item
  matnr TYPE vbap-matnr,               " Material Number
  kwmeng TYPE vbap-kwmeng,             " Ordered Quantity
  meins TYPE vbap-meins,               " Unit of Measure
  netpr TYPE vbap-netpr,               " Net Price
  waerk TYPE vbap-waerk,               " Currency
 END OF type_s_order.
DATA:
*--------------------------------------------------------------------*
*                FIELD STRING TO HOLD CUSTOMER DETAILS
*--------------------------------------------------------------------*
 fs_cust TYPE type_s_cust,
*--------------------------------------------------------------------*
*               INTERNAL TABLE TO HOLD CUSTOMER DETAILS
*--------------------------------------------------------------------*
 t_cust LIKE TABLE OF fs_cust,
*--------------------------------------------------------------------*
*                 FIELD STRING TO HOLD ORDER DETAILS
*--------------------------------------------------------------------*
 fs_order TYPE type_s_order,
*--------------------------------------------------------------------*
*                 INTERNAL TABLE TO HOLD ORDER DETAILS
*--------------------------------------------------------------------*
 t_order LIKE TABLE OF fs_order,
 w_field(20).                          " Cursor Position
*--------------------------------------------------------------------*
*                        START-OF-SELECTION
*--------------------------------------------------------------------*
START-OF-SELECTION.
  SET PF-STATUS 'CUST'.
  PERFORM selection.
*--------------------------------------------------------------------*
*                         END-OF-SELECTION
*--------------------------------------------------------------------*
END-OF-SELECTION.
  PERFORM display.
*--------------------------------------------------------------------*
*                             TOP-OF-PAGE
*--------------------------------------------------------------------*
TOP-OF-PAGE.
  PERFORM top-of-page.
*--------------------------------------------------------------------*
*                         AT LINE-SELECTION
*--------------------------------------------------------------------*
AT LINE-SELECTION.
  PERFORM at_line_selection.
*--------------------------------------------------------------------*
*              AT LINE-SELECTION DURING LINE SELECTION
*--------------------------------------------------------------------*
TOP-OF-PAGE DURING LINE-SELECTION.
  PERFORM top_of_page_during.
*--------------------------------------------------------------------*
*                         AT USER-COMMAND
*--------------------------------------------------------------------*
AT USER-COMMAND.
  PERFORM user_command.
*&---------------------------------------------------------------------*
*&      Form  SELECTION
*&---------------------------------------------------------------------*
* Subroutine to fetch data from KNA1 and VBAK
*----------------------------------------------------------------------*
* There are no interface parameters to be passed to this subroutine
*----------------------------------------------------------------------*
FORM selection .
  SELECT   a~kunnr                     " Customer Number
           a~name1                     " Customer Name
           b~vbeln                     " Order Number
           FROM kna1 AS a
           INNER JOIN vbak AS b
           ON a~kunnr = b~kunnr
           INTO CORRESPONDING FIELDS OF TABLE t_cust
           WHERE a~kunnr IN s_kunnr.
ENDFORM.                               " SELECTION
*&---------------------------------------------------------------------*
*&      Form  DISPLAY
*&---------------------------------------------------------------------*
* Subroutine to display data
*----------------------------------------------------------------------*
* There are no interface parameters to be passed to this subroutine
*----------------------------------------------------------------------*
FORM display .
  LOOP AT t_cust INTO fs_cust.
    WRITE:
      /1 fs_cust-kunnr COLOR 4,
      20 fs_cust-name1 COLOR 4,
      40 fs_cust-vbeln COLOR 4.
    HIDE:
    fs_cust-kunnr,
    fs_cust-name1,
    fs_cust-vbeln.
  ENDLOOP.                             " LOOP AT T_CUST
ENDFORM.                               " DISPLAY
*&---------------------------------------------------------------------*
*&      Form  TOP-OF-PAGE
*&---------------------------------------------------------------------*
* Subroutine for heading
*----------------------------------------------------------------------*
* There are no interface parameters to be passed to this subroutine
*----------------------------------------------------------------------*
FORM top-of-page .
  WRITE:
       /1 text-011 COLOR 5,
       20 text-005 COLOR 5,
       40 text-006 COLOR 5.
ENDFORM.                               " TOP-OF-PAGE
*&---------------------------------------------------------------------*
*&      Form  AT_LINE_SELECTION
*&---------------------------------------------------------------------*
* Subroutine to fetch data from VBAP
*----------------------------------------------------------------------*
* There are no interface parameters to be passed to this subroutine
*----------------------------------------------------------------------*
FORM at_line_selection .
  SELECT  posnr                        " Sales Document Item
          matnr                        " Material Number
          kwmeng                       " Ordered Quantity
          meins                        " Unit of Measure
          netpr                        " Net Price
          waerk                        " Currency
          FROM vbap INTO CORRESPONDING FIELDS OF TABLE t_order
          WHERE vbeln EQ fs_cust-vbeln.
  CLEAR fs_cust-vbeln.
  IF sy-subrc <> 0.
    MESSAGE text-004 TYPE 'I'.
  ENDIF.                               " IF SY-SUBRC <> 0.
  LOOP AT t_order INTO fs_order .
    WRITE:
   /1 fs_order-posnr COLOR 4,
   20 fs_order-matnr COLOR 4,
   27 fs_order-kwmeng UNIT fs_order-meins COLOR 4,
   53 fs_order-netpr CURRENCY fs_order-waerk COLOR 4.
  ENDLOOP.                             " LOOP AT T_ORDER
ENDFORM.                               " AT_LINE_SELECTION
*&---------------------------------------------------------------------*
*&      Form  TOP_OF_PAGE_DURING
*&---------------------------------------------------------------------*
* Subroutine for secondary list heading
*----------------------------------------------------------------------*
* There are no interface parameters to be passed to this subroutine
*----------------------------------------------------------------------*
FORM top_of_page_during .
  WRITE:
     /1 text-007 COLOR 5,
      20 text-008 COLOR 5,
      40 text-009 COLOR 5,
      60 text-010 COLOR 5.
ENDFORM.                               " TOP_OF_PAGE_DURING
*&---------------------------------------------------------------------*
*&      Form  USER_COMMAND
*&---------------------------------------------------------------------*
* Subroutine for pushbuttons
*----------------------------------------------------------------------*
* There are no interface parameters to be passed to this subroutine
*----------------------------------------------------------------------*
FORM user_command .
  CASE sy-ucomm.
    WHEN 'CUSTOMER'.
      GET CURSOR FIELD w_field.
      IF w_field EQ 'FS_CUST-KUNNR'.
        SET PARAMETER ID 'KUN' FIELD fs_cust-kunnr.
        CALL TRANSACTION 'VD03'.
      ELSEIF w_field NE 'FS_CUST-KUNNR'.
        MESSAGE text-001 TYPE 'E'.
      ENDIF.                           " IF W_FIELD
    WHEN 'ORDER'.
      GET CURSOR FIELD w_field.
      IF w_field EQ 'FS_CUST-VBELN'.
        SET PARAMETER ID 'AUN' FIELD fs_cust-vbeln.
        CALL TRANSACTION 'VA03'.
      ELSEIF  w_field NE 'FS_CUST-VBELN'.
        MESSAGE text-002 TYPE 'E'.
      ENDIF.                           " IF W_FIELD
  ENDCASE.                             " CASE SY-UCOMM
ENDFORM.                               " USER_COMMAND

Here I will discuss about Memory id concept .Concept of memory id can be very useful in different cases. In cases where we need to transfer values from one program to other program

which are not having any connection from which we can take those values. we use export- imort for this purpose.

Here is the form where this concept has been used :

Error rendering macro 'code': Invalid value specified for parameter 'com.atlassian.confluence.ext.code.render.InvalidValueException'
FORM  f_fetch_details   TABLES  fp_it_input_tab STRUCTURE itcsy
                                fp_it_ouput_tab STRUCTURE itcsy.

  FIELD-SYMBOLS: <l_fs_output>  TYPE itcsy.

  READ TABLE fp_it_input_tab INTO l_wa_input INDEX 1.
  IF sy-subrc EQ 0.
    l_v_belnr = l_wa_input-value.
  ENDIF.

  IMPORT v_id TO l_it_with_item FROM MEMORY ID l_v_belnr.
  IF sy-subrc IS INITIAL.
    FREE MEMORY ID l_v_belnr.
  ENDIF.

  IF l_it_with_item IS INITIAL.

    SELECT  augbl FROM with_item INTO TABLE tb_clrng_doc
      WHERE belnr EQ l_v_belnr.

    SORT tb_clrng_doc.
    DELETE ADJACENT DUPLICATES FROM tb_clrng_doc.

    IF NOT tb_clrng_doc[] IS INITIAL.

      SELECT witht INTO TABLE l_it_with_item
          FROM with_item
     FOR ALL ENTRIES IN tb_clrng_doc
          WHERE belnr = tb_clrng_doc-augbl
          AND   bukrs = `1065`
          AND NOT ctnumber = ``.
    ELSE.

      SELECT witht INTO TABLE l_it_with_item
          FROM with_item
          WHERE belnr = l_v_belnr
         AND   bukrs = `1065`
         AND NOT ctnumber = ``.
    ENDIF.
  ENDIF.

*  read the contents at index 1
  CLEAR wa_it_with_item.
  READ TABLE l_it_with_item INTO wa_it_with_item INDEX 1.
  IF sy-subrc IS INITIAL.
    l_v_witht = wa_it_with_item-witht.
    DELETE l_it_with_item INDEX sy-tabix.
    IF   l_it_with_item IS NOT INITIAL.
      EXPORT v_id FROM l_it_with_item TO MEMORY ID l_v_belnr.
    ENDIF.
  ENDIF.

  CLEAR l_v_heading.
  SELECT SINGLE text40
    INTO l_v_heading FROM t059u
    WHERE spras EQ 'S' AND
          land1 EQ 'AR' AND
          witht EQ l_v_witht.

  READ TABLE fp_it_ouput_tab ASSIGNING <l_fs_output> INDEX  1.
  MOVE l_v_heading TO <l_fs_output>-value.
  CLEAR l_v_witht.

ENDFORM.                    "f_fetch_details
Error rendering macro 'code': Invalid value specified for parameter 'com.atlassian.confluence.ext.code.render.InvalidValueException'
REPORT  zsap_memory.
SET PARAMETER ID 'AUN' FIELD '5227'.
CALL TRANSACTION 'VA03' AND SKIP FIRST SCREEN.
Error rendering macro 'code': Invalid value specified for parameter 'com.atlassian.confluence.ext.code.render.InvalidValueException'
REPORT yclii_memories01.
DATA: val(10) TYPE c VALUE 'Hello'.

START-OF-SELECTION.

  SET PARAMETER ID 'PARA1' FIELD val.
  IF sy-subrc = 0.
    MESSAGE s037(yclii_mc01).
  ELSE.
    MESSAGE s038(yclii_mc01) DISPLAY LIKE 'E'.
  ENDIF.

*************************************************************

REPORT yclii_memories02.
DATA valu(15) TYPE c.

GET PARAMETER ID 'PARA1' FIELD valu.

WRITE:/5 valu.

Create the corresponding message in SE91.

List of all pages

Pages at first level

The following are the open sql statements....

1.aggregate functions
2.select distinct
3.outer join
4.package size
5.bypassing buffer
6.client specified
7.sub query
8.having
9.for all entries in
10.fields in internal table
11.where condition in internal table
12.order by in internal table

AGGREGATE FUNCTIONS:

Error rendering macro 'code': Invalid value specified for parameter 'com.atlassian.confluence.ext.code.render.InvalidValueException'
REPORT yclii_osql01 LINE-SIZE 140.
DATA: matnr    TYPE matnr,
      maktx    TYPE maktx,
      vrkme    TYPE vrkme,
      cont     TYPE i,
      total    TYPE fkimg,
      max      TYPE fkimg,
      min      TYPE fkimg.
*******************************************
START-OF-SELECTION.
  SELECT matnr maktx vrkme COUNT( * )  SUM( fkimg ) MAX( fkimg ) MIN( fkimg ) FROM
   yclii_vbrp_makt INTO (matnr,maktx,vrkme,cont,total,max,min) GROUP BY matnr maktx vrkme.
    WRITE:/5(4) sy-dbcnt, matnr USING NO EDIT MASK, maktx, vrkme, cont, total, max, min.
  ENDSELECT.

SELECT DISTINCT:

Error rendering macro 'code': Invalid value specified for parameter 'com.atlassian.confluence.ext.code.render.InvalidValueException'
REPORT  yclii_osql02 LINE-SIZE 100.
DATA: BEGIN OF cust_stru,
       kunnr  TYPE kunnr,
       name1  TYPE name1_gp,
       ort01  TYPE ort01_gp,
      END OF cust_stru.
*************************************
START-OF-SELECTION.
  SELECT DISTINCT kunnr name1 ort01 FROM yclii_kna1_vbrk INTO cust_stru ORDER BY kunnr.
    WRITE:/5(4) sy-dbcnt, cust_stru-kunnr USING NO EDIT MASK, cust_stru-name1, cust_stru-ort01.
  ENDSELECT.

OUTER JOIN:

Error rendering macro 'code': Invalid value specified for parameter 'com.atlassian.confluence.ext.code.render.InvalidValueException'
REPORT  yclii_osql03.
TYPES: BEGIN OF cust_bills_tp,
        kunnr     TYPE kunnr,
        name1     TYPE name1_gp,
        vbeln     TYPE vbeln,
        fkdat_rl  TYPE fkdat_rl,
       END OF cust_bills_tp.
*********************************
DATA: cust_bills_stru TYPE cust_bills_tp,
      cust_bills_tab  TYPE STANDARD TABLE OF cust_bills_tp.
******************************************************************
START-OF-SELECTION.
  SELECT kna1~kunnr kna1~name1 vbrk~vbeln vbrk~fkdat_rl
         INTO TABLE cust_bills_tab
         FROM kna1
         LEFT OUTER JOIN vbrk ON  kna1~mandt     =  vbrk~mandt
                                  AND kna1~kunnr = vbrk~kunag.
  LOOP AT cust_bills_tab INTO cust_bills_stru.
    WRITE :/5(5) sy-tabix,cust_bills_stru-kunnr USING NO EDIT MASK, cust_bills_stru-name1,
     cust_bills_stru-vbeln, cust_bills_stru-fkdat_rl.
  ENDLOOP.

PACKAGE SIZE:

1)

Error rendering macro 'code': Invalid value specified for parameter 'com.atlassian.confluence.ext.code.render.InvalidValueException'
REPORT  yclii_osql04 LINE-SIZE 120.
DATA: cust_tab TYPE yclii_cust_tab WITH HEADER LINE,
      cntr(3)  TYPE p DECIMALS 0.
PARAMETERS: pksz(4)  TYPE n DEFAULT 1000.

START-OF-SELECTION.
**************************************************************************************
* if no of rows/data is very large putting pressure on ram, the in this scenario     *
* data can be fetched in batches of smaller size.                                    *
* in the present scenario,you are fetching data in batches of 1000 rows at a time.   *
* this batch size can be specified with the phrase PACKAGE SIZE & a literal/variable.*
* every time batch of rows is fetched, existing data in the internal table is washed *
* /deleted. so at any instant only one batch of data/rows is existing in the internal*
* table.                                                                             *
**************************************************************************************
  SELECT kunnr anred name1 stras ort01 pstlz FROM kna1 INTO TABLE cust_tab PACKAGE SIZE
   pksz.
    LOOP AT cust_tab.
      cntr = cntr + 1.
      WRITE:/5(5) cntr, cust_tab-kunnr USING NO EDIT MASK, cust_tab-name1, cust_tab-ort01.
    ENDLOOP.
    SKIP 2.
  ENDSELECT.

2)

Error rendering macro 'code': Invalid value specified for parameter 'com.atlassian.confluence.ext.code.render.InvalidValueException'
REPORT  yclii_osql05 LINE-SIZE 120.
DATA: cust_tab TYPE yclii_cust_tab WITH HEADER LINE,
      cntr(3)  TYPE p DECIMALS 0.
PARAMETERS: pksz(4)  TYPE n DEFAULT 1000.

START-OF-SELECTION.
**************************************************************************************
* if no of rows/data is very large putting pressure on network, then in this scenario*
* data can be fetched in batches of smaller size & appended to the internal table    *
* in the present scenario,you are fetching data in batches of 1000 rows at a time.   *
* this batch size can be specified with the phrase PACKAGE SIZE & a literal/variable.*
* every time batch of rows is fetched,existing data in the internal table is appended*
* to. at the end of SELECT.. ENDSELECT loop, internal table contains all the fetched *
* in the batches.                                                                    *
**************************************************************************************
  SELECT kunnr anred name1 stras ort01 pstlz FROM kna1 APPENDING TABLE cust_tab
    PACKAGE SIZE pksz.
  ENDSELECT.
  LOOP AT cust_tab.
    WRITE:/5(5) sy-tabix, cust_tab-kunnr USING NO EDIT MASK, cust_tab-name1, cust_tab-ort01.
    cntr = sy-tabix MOD pksz.
    IF cntr = 0.
      SKIP 2.
    ENDIF.
  ENDLOOP.

SUBQUERY:

Error rendering macro 'code': Invalid value specified for parameter 'com.atlassian.confluence.ext.code.render.InvalidValueException'
REPORT  yclii_osql06.
DATA: BEGIN OF bill_stru,
       vbeln     TYPE vbeln,
       fkdat_rl  TYPE fkdat_rl,
       netwr     TYPE netwr,
       waerk     TYPE waerk,
      END OF bill_stru,
      bill_tab LIKE STANDARD TABLE OF bill_stru.
PARAMETERS: city TYPE ort01_gp DEFAULT 'CHICAGO'.
***************************************************
* bills of customers of a specified city **********
***************************************************
START-OF-SELECTION.
  SELECT vbeln fkdat_rl netwr waerk FROM vbrk INTO TABLE bill_tab WHERE kunag IN
   ( SELECT kunnr FROM kna1 WHERE ort01 = city ).
  LOOP AT bill_tab INTO bill_stru.
    WRITE:/5(5) sy-tabix, bill_stru-vbeln, bill_stru-fkdat_rl, (15) bill_stru-netwr,
     bill_stru-waerk.
  ENDLOOP.

FOR ALL ENTRIES IN:

Error rendering macro 'code': Invalid value specified for parameter 'com.atlassian.confluence.ext.code.render.InvalidValueException'
REPORT  yclii_osql07.
DATA: BEGIN OF vbrk_tab OCCURS 0,
       vbeln   TYPE vbrk-vbeln,
       fkdat   TYPE vbrk-fkdat,
       kunag   TYPE vbrk-kunag,
       netwr   TYPE vbrk-netwr,
       waerk   TYPE vbrk-waerk,
      END OF vbrk_tab,
      BEGIN OF vbrp_tab OCCURS 0,
       vbeln   TYPE vbrp-vbeln,
       matnr   TYPE vbrp-matnr,
       fkimg   TYPE vbrp-fkimg,
       vrkme   TYPE vbrp-vrkme,
      END OF vbrp_tab.
***************************************
SELECT-OPTIONS cust_cd FOR vbrk_tab-kunag.
******************************************
INITIALIZATION.
  cust_cd-sign    = 'I'.
  cust_cd-option  = 'EQ'.
  cust_cd-low     = '0000000099'.
  APPEND cust_cd.
*****************************************
START-OF-SELECTION.
  SELECT vbeln fkdat kunag netwr waerk FROM vbrk INTO TABLE vbrk_tab WHERE kunag IN
   cust_cd.
  SELECT vbeln matnr fkimg vrkme FROM vbrp INTO TABLE vbrp_tab FOR ALL ENTRIES IN vbrk_tab
   WHERE vbeln = vbrk_tab-vbeln.
  BREAK-POINT.

FIELDS IN INTERNAL TABLE:

Error rendering macro 'code': Invalid value specified for parameter 'com.atlassian.confluence.ext.code.render.InvalidValueException'
REPORT  yclii_osql08 LINE-SIZE 140.
TABLES: kna1.
*DATA KNA1 TYPE KNA1.
DATA: fields(15) TYPE c OCCURS 0 WITH HEADER LINE.

START-OF-SELECTION.
  fields = 'KUNNR'.
  APPEND fields.
  fields = 'NAME1'.
  APPEND fields.
  fields = 'STRAS'.
  APPEND fields.
  fields = 'ORT01'.
  APPEND fields.
  SELECT (fields) FROM kna1 INTO CORRESPONDING FIELDS OF kna1.
    WRITE:/5(5) sy-dbcnt, kna1-kunnr USING NO EDIT MASK, kna1-name1, kna1-stras, kna1-ort01.
  ENDSELECT.

WHERE CONDITION IN INTERNAL TABLE:

Error rendering macro 'code': Invalid value specified for parameter 'com.atlassian.confluence.ext.code.render.InvalidValueException'
REPORT  yclii_osql09 LINE-SIZE 120.
DATA: cust_tab       TYPE yclii_cust_tab WITH HEADER LINE,
      conditions(70) TYPE c OCCURS 0 WITH HEADER LINE.

START-OF-SELECTION.
  conditions = 'ORT01 = ''BERLIN'' AND '.
  APPEND conditions.
  conditions = '( NAME1 LIKE ''A%'' OR NAME1 LIKE ''G%'' )'.
  APPEND conditions.
  SELECT kunnr anred name1 stras ort01 pstlz FROM kna1 INTO TABLE cust_tab WHERE
   (conditions).
  SORT cust_tab BY name1.
  LOOP AT cust_tab.
    WRITE:/5(5) sy-tabix, cust_tab-kunnr USING NO EDIT MASK, cust_tab-name1, cust_tab-ort01.
  ENDLOOP.

ORDER BY IN INTERNAL TABLE:

Error rendering macro 'code': Invalid value specified for parameter 'com.atlassian.confluence.ext.code.render.InvalidValueException'
REPORT  yclii_osql10 LINE-SIZE 130.
DATA : cust_tab     TYPE yclii_cust_tab,
       cust_stru    TYPE LINE OF yclii_cust_tab,
       sort_ed(50)  TYPE c,
       sort_ar      LIKE STANDARD TABLE OF sort_ed.
****************************************
START-OF-SELECTION.
  sort_ed  = 'ORT01 ASCENDING NAME1 DESCENDING'.
  APPEND sort_ed TO sort_ar.
  SELECT kunnr anred name1 stras ort01 pstlz FROM kna1 INTO TABLE cust_tab WHERE
   ort01 <> ' ' ORDER BY (sort_ar).
  LOOP AT cust_tab INTO cust_stru.
    WRITE:/5(5) sy-tabix, cust_stru-ort01, cust_stru-name1, cust_stru-kunnr
     USING NO EDIT MASK.
  ENDLOOP.

CLIENT SPECIFIED:

Error rendering macro 'code': Invalid value specified for parameter 'com.atlassian.confluence.ext.code.render.InvalidValueException'
REPORT  yclii_osql11.
DATA : BEGIN OF cust_stru,
        mandt   TYPE kna1-mandt,
        kunnr   TYPE kna1-kunnr,
        name1   TYPE kna1-name1,
       END OF cust_stru,
       cust_tab LIKE STANDARD TABLE OF cust_stru.
SELECT-OPTIONS client FOR cust_stru-mandt.

START-OF-SELECTION.
  SELECT mandt kunnr name1 FROM kna1 CLIENT SPECIFIED INTO TABLE cust_tab WHERE
   mandt IN client.
  LOOP AT cust_tab INTO cust_stru.
    WRITE:/5(5) sy-tabix, cust_stru-mandt, cust_stru-kunnr USING NO EDIT MASK,
     cust_stru-name1.
  ENDLOOP.

Group-by statement is really helpful to avoid fetching high-volume of data into your program when you need that data sum(collect) on currency and quantity fields. 

*Extracts from program Ztab2002
* START-OF-SELECTION

SELECT kalnr kalka bwvar meeht SUM( menge )
  INTO TABLE i_ckis FROM ckis
  WHERE kadky <= sy-datum
    AND tvers = '01'
    AND kalka IN ('01','Z1','Z2')
    AND bwvar IN ('Z01','Z02','Z03','Z04','Z07')
*     and kkzst = ' '
    AND kkzma = ' '
    AND typps = 'E'
    AND ( kstar <> 800040 OR kstar <> 800050 )
    AND ( meeht = 'MIN' OR meeht = 'H' )
  GROUP BY kalnr kalka bwvar meeht.

* Perform actual processing
PERFORM get_associated_labour_hours.

*&---------------------------------------------------------------------*
*&      Form  get_associated_labour_hours
*&---------------------------------------------------------------------*
FORM get_associated_labour_hours.
* Determine start position and then process single record for given key
* i_ckis is sorted on kalnr kalka bwvar meeht with menge summated.
  READ TABLE i_ckis WITH KEY kalnr = w_keko-kalnr
                             kalka = w_keko-kalka
                             bwvar = w_keko-bwvar
                             meeht = 'H'          BINARY SEARCH.
  IF sy-subrc = 0.
    d_lab_hrs =  i_ckis-menge * 60.
  ENDIF.

  READ TABLE i_ckis WITH KEY kalnr = w_keko-kalnr
                             kalka = w_keko-kalka
                             bwvar = w_keko-bwvar
                             meeht = 'MINS'       BINARY SEARCH.
  IF sy-subrc = 0.
    d_lab_hrs =  d_lab_hrs + i_ckis-menge.
  ENDIF.

  d_lab_hrs = d_lab_hrs / w_keko-losgr.
  d_lab_hrs = d_lab_hrs / 60.          "Convert from mins into hours
ENDFORM.                               " GET_LABOUR_HOURS_ASSOCIATED
 

Submitted By:  Ramganesan Karuppaiyah

Submitted On: February 7, 2007 

This  is mainly for Executing a Query Statement by passing the Parameter to It.The Great advantage of it is we can pass the table and fields at run time.It leads to minimize the development time. This can be achieved by Using Macro.

What is Macro?:

Macro is a set of executable statement/s which can be called in a program.
Whenever it is called in the program its replaces the statement which is defined inside the macro.

Code:

DEFINE macro_name.
  "Set of statements to be executed.
END-OF-DEFINITION.
 

Note:
It is also possible to pass parameters to the MACRO.

Steps Involved

  1. Here I am declaring a macro which can accept upto 4 Parameters during runtime.
  2. Declaring necessary data types.
  3. Calling Macro in the Program.

 

DEFINE s.
  select &1
  from &2
  into table &3
  where &4.
END-OF-DEFINITION.

DATA: t_mara TYPE mara OCCURS 0.
DATA: l_mara(4) VALUE 'MARA',
      l_s(6) VALUE 'SELECT',
      l_field(5) VALUE '*',
      l_table(6) VALUE 'T_MARA',
      l_query TYPE string VALUE 'MATNR = ''000000000000000001'''.

FIELD-SYMBOLS: <fs> TYPE table.

ASSIGN t_mara TO <fs>.
s (l_field) (l_mara) <fs> (l_query).
 

Things to remember before using for all entries:

1>     Always select all the key fields, even you are not using the fields further in program.

2>     Sort the table by fields in where clause.

3>     Check table is not blank before using for all entries.

4>    Delete the adjacent duplicates from the driver table. Other wise, for the same entry system will check redundantly.

 

Select field1 field2 field3 into table it_tab1
      From table1 where conditions.

Sort it_tab1 by field1 field2.

Delete adjacent duplicates from it_itab1 comparing field1 field2.

If not it_tab1[] is initial.
   Select key_field1   key_field2   key_field3.....   Key_fieldn  field1
   From table2 into it_tab2
   For all entries in it_tab1
   Where key_field1 = field1
  And key_field2 = field2.
Endif.


 Important Notice: While For All Entries has its uses (for example in BI Routines), in most cases INNER JOIN is more efficient, and leads to more compact, more readable code. INNER JOIN should ALWAYS be used in preference to For All Entries. This is especially true if for ABAP with HANA


Author: Sangyeul Han
Submitted: July 26, 2007
Description: Sometimes, you want to process abap code with parallel processing. In help you read the syntax following.

  • CALL FUNCTION func STARTING NEW TASK TASK
  • CALL FUNCTION func IN BACKGROUND TASK

But, you do not satisfied with "STARTING NEW TASK TASK" because of the session count 6. So, you decide to use "IN BACKGROUND TASK". After a while you also find that this syntax does not make parallel processing. This time, You can add "AS SEPARATE UNIT". First of all, your Function Module must be RFC. Let's go into the code.

Error rendering macro 'code': Invalid value specified for parameter 'com.atlassian.confluence.ext.code.render.InvalidValueException'
REPORT  y_test_syhan_008.

TABLES : mara,
         ysyhan_01.

DATA : BEGIN OF itab OCCURS 0,
         mtart LIKE ysyhan_01-mtart,
         quant LIKE ysyhan_01-quant,
         meins LIKE ysyhan_01-meins,
       END OF itab.

SELECT mtart INTO mara-mtart FROM mara.
  itab-mtart = mara-mtart.
  itab-quant = itab-quant + 1.
  itab-meins = 'EA'.
  COLLECT itab.  CLEAR itab.
ENDSELECT.

DELETE FROM ysyhan_01.

LOOP AT itab.
  CALL FUNCTION 'YSYH_MTART_QUANT'
    IN BACKGROUND TASK
    AS SEPARATE UNIT
*    IN UPDATE TASK
    EXPORTING
      mtart = itab-mtart
      quant = itab-quant
      meins = itab-meins.
  COMMIT WORK.
  WAIT UP TO 10 SECONDS.
ENDLOOP.

Code summary and explanation!

  • AS SEPARATE UNIT 
  • COMMIT WORK

Execute this ABAP Program and monitor SM50. In interval 10 seconds, dialog processes occur.
Caution. if processes count exceeds the restriction no, other SAP user will complain to you.

Good luck~

??






REPORT zhashed_table .

TYPES: BEGIN OF t_foo,
        field1 TYPE char2,
        field2 TYPE char2,
        field3 TYPE char2,
        field4 TYPE i,
       END OF t_foo.

DATA: lt_foo TYPE HASHED TABLE OF t_foo
               WITH UNIQUE KEY field1 field2 field3.

DATA: ls_foo LIKE LINE OF lt_foo.

FIELD-SYMBOLS: <ls_foo> LIKE LINE OF lt_foo.

* Must assign it to use it.
ASSIGN ls_foo TO <ls_foo>.

CLEAR <ls_foo>.
<ls_foo>-field1 = 'AB'.
<ls_foo>-field2 = 'CD'.
<ls_foo>-field3 = 'EF'.
<ls_foo>-field4 = '2'.
INSERT <ls_foo> INTO TABLE lt_foo.

CLEAR <ls_foo>.
<ls_foo>-field1 = 'AB'.
<ls_foo>-field2 = 'CD'.
<ls_foo>-field3 = 'EF'.
<ls_foo>-field4 = '2'.
INSERT <ls_foo> INTO TABLE lt_foo.
IF sy-subrc  NE 0.
  WRITE:/ 'this is  duplicate key '.
ENDIF.
 

Description
For Example The Stack Memory of the execution of a program is this:

  1. Program Z1 --> call function F2
  2. Function F2 of function group Z2 --> call function F3
  3. Function F3 of function group Z3.

 You are inside the FM F3 and you want to access the internal table LT_IT that is declare in program Z1 and you don't have it in the interface of the function.

Error rendering macro 'code': Invalid value specified for parameter 'com.atlassian.confluence.ext.code.render.InvalidValueException'
DATA: l_stack(30) TYPE c.
DATA: lw_it TYPE xxx.

FIELD-SYMBOLS: <lt_it> TYPE STANDARD TABLE.

CLEAR l_stack.
MOVE '(Z1)LT_IT[]' TO l_stack.
ASSIGN (l_stack) TO <lt_it>.

LOOP AT <lt_it> INTO lw_it.
* here you access to the table.
ENDLOOP.

Important: You must know the sequence of the stack to do that. Otherwise if the function F3 is call from an other program you will not have access to the lt_it table.


  • No labels