Skip to end of metadata
Go to start of metadata

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</

  • No labels