ABAP - Check objects (Instances)
In this article we will show you how you can analyze instances and react to them correctly, for example if you hand them over during processing and want to react individually.
Table of contents
You cannot always assume that your method interface will be supplied correctly, especially if you allow a generic object type. For such cases there are two new commands that should make working with instances a little easier for you.
Class model
For today's examples we will implement some classes and interfaces in hierarchy to demonstrate how the two new commands work. In the first step, the data model, based on the abstract class LCL_VEHICLE and the corresponding inheriting classes.
The second series of tests is based on an interface and the two implementing classes. The animals implement the appropriate interface and method.
For the hierarchies shown above, here is the corresponding minimum definition in ABAP. We use the transferred object of the class runner for the output.
*** Class and interface definitions
CLASS lcl_vehicle DEFINITION ABSTRACT.
PUBLIC SECTION.
METHODS:
speed_up
IMPORTING
io_output TYPE REF TO if_oo_adt_classrun_out.
ENDCLASS.
CLASS lcl_car DEFINITION INHERITING FROM lcl_vehicle.
PUBLIC SECTION.
METHODS:
open_luggage_space
IMPORTING
io_output TYPE REF TO if_oo_adt_classrun_out.
ENDCLASS.
CLASS lcl_bwm DEFINITION INHERITING FROM lcl_car.
ENDCLASS.
CLASS lcl_truck DEFINITION INHERITING FROM lcl_vehicle.
PUBLIC SECTION.
METHODS:
open_bedroom
IMPORTING
io_output TYPE REF TO if_oo_adt_classrun_out.
ENDCLASS.
CLASS lcl_man DEFINITION INHERITING FROM lcl_truck.
ENDCLASS.
CLASS lcl_plane DEFINITION INHERITING FROM lcl_vehicle.
ENDCLASS.
INTERFACE lif_animal.
METHODS:
make_sound
IMPORTING
io_output TYPE REF TO if_oo_adt_classrun_out.
ENDINTERFACE.
CLASS lcl_cat DEFINITION.
PUBLIC SECTION.
INTERFACES: lif_animal.
ENDCLASS.
CLASS lcl_dog DEFINITION.
PUBLIC SECTION.
INTERFACES: lif_animal.
ENDCLASS.
*** Implementations of the classes
CLASS lcl_car IMPLEMENTATION.
METHOD open_luggage_space.
io_output->write( 'I am opening the luggage space.' ).
ENDMETHOD.
ENDCLASS.
CLASS lcl_truck IMPLEMENTATION.
METHOD open_bedroom.
io_output->write( 'I am opening the bedroom.' ).
ENDMETHOD.
ENDCLASS.
CLASS lcl_cat IMPLEMENTATION.
METHOD lif_animal~make_sound.
io_output->write( 'Miou!' ).
ENDMETHOD.
ENDCLASS.
CLASS lcl_dog IMPLEMENTATION.
METHOD lif_animal~make_sound.
io_output->write( 'Wuff!' ).
ENDMETHOD.
ENDCLASS.
CLASS lcl_vehicle IMPLEMENTATION.
METHOD speed_up.
io_output->write( 'Over 9000!' ).
ENDMETHOD.
ENDCLASS.
IS INSTANCE OF
The command checks a transferred object (must not be initial) whether it implements the type of a class or an interface. This also works correctly above the hierarchy of objects. This ensures that the methods and attributes of the checked class are available for the object. You can also use the command to implement your error handling.
DATA(lo_bwm) = NEW lcl_bwm( ).
IF lo_bwm IS NOT INSTANCE OF lcl_vehicle.
" Error handling
ENDIF.
In the example above, we have created an instance of the LCL_BWM class, this can be just such a transfer parameter in a method. The next step is to check whether the object belongs to the abstract class LCL_VEHICLE. If this is not the case, appropriate error handling can be implemented.
CASE TYPE OF
This new command is a CASE with some special features and so far optimized for instances. Here you can check an object reference (not initial) against different types (classes and interfaces) and react to them. This is particularly suitable if you want to react to any object in a processing. In this case we provide a method that can accommodate all types of objects.
METHODS:
react_for_different_objects
IMPORTING
io_object TYPE REF TO object
io_output TYPE REF TO if_oo_adt_classrun_out
RAISING
cx_sy_conversion_unknown_unit.
You can then pass all types of objects to this method and this method reacts accordingly to the type passed.
METHOD react_for_different_objects.
CASE TYPE OF io_object.
WHEN TYPE lif_animal INTO DATA(lo_animal).
lo_animal->make_sound( io_output ).
WHEN TYPE lcl_car INTO DATA(lo_car).
lo_car->open_luggage_space( io_output ).
WHEN TYPE lcl_truck INTO DATA(lo_truck).
lo_truck->open_bedroom( io_output ).
WHEN TYPE lcl_vehicle INTO DATA(lo_vehicle).
lo_vehicle->speed_up( io_output ).
WHEN OTHERS.
RAISE EXCEPTION NEW cx_sy_conversion_unknown_unit( ).
ENDCASE.
ENDMETHOD.
With the addition INTO you create an instance of the comparison type in the background with a CAST. This then gives you the opportunity to access attributes and methods directly (as in the example above). This can be used, for example, to trigger further processing.
Example
At this point the complete example of the class with the main and test methods. The messages are output via the console in Eclipse.
CLASS zcl_bs_demo_instance DEFINITION PUBLIC FINAL CREATE PUBLIC.
PUBLIC SECTION.
INTERFACES if_oo_adt_classrun.
PROTECTED SECTION.
PRIVATE SECTION.
METHODS:
react_for_different_objects
IMPORTING
io_object TYPE REF TO object
io_output TYPE REF TO if_oo_adt_classrun_out
RAISING
cx_sy_conversion_unknown_unit.
ENDCLASS.
CLASS zcl_bs_demo_instance IMPLEMENTATION.
METHOD if_oo_adt_classrun~main.
DATA(lo_bwm) = NEW lcl_bwm( ).
IF lo_bwm IS INSTANCE OF lcl_vehicle.
out->write( 'LO_BMW is instance from object LCL_VEHICLE' ).
ENDIF.
DATA(lo_dog) = NEW lcl_dog( ).
IF lo_dog IS INSTANCE OF lif_animal.
out->write( 'LO_DOG is instance from interface LIF_ANIMAL' ).
ENDIF.
react_for_different_objects( io_output = out io_object = NEW lcl_car( ) ).
react_for_different_objects( io_output = out io_object = NEW lcl_truck( ) ).
react_for_different_objects( io_output = out io_object = NEW lcl_bwm( ) ).
react_for_different_objects( io_output = out io_object = NEW lcl_man( ) ).
react_for_different_objects( io_output = out io_object = NEW lcl_plane( ) ).
react_for_different_objects( io_output = out io_object = NEW lcl_dog( ) ).
react_for_different_objects( io_output = out io_object = NEW lcl_cat( ) ).
ENDMETHOD.
METHOD react_for_different_objects.
CASE TYPE OF io_object.
WHEN TYPE lif_animal INTO DATA(lo_animal).
lo_animal->make_sound( io_output ).
WHEN TYPE lcl_car INTO DATA(lo_car).
lo_car->open_luggage_space( io_output ).
WHEN TYPE lcl_truck INTO DATA(lo_truck).
lo_truck->open_bedroom( io_output ).
WHEN TYPE lcl_vehicle INTO DATA(lo_vehicle).
lo_vehicle->speed_up( io_output ).
WHEN OTHERS.
RAISE EXCEPTION NEW cx_sy_conversion_unknown_unit( ).
ENDCASE.
ENDMETHOD.
ENDCLASS.
The result generated from the run of the class then looks like this. The corresponding branches in the REACT method were run through:
Conclusion
Working with generic objects doesn't always have to be difficult. With the two new commands you can easily filter out and validate the correct object and react accordingly. In the future, your programs will get a little more stability and reliability.
Sources:
SAP Documentation - IS INSTANCE OF
SAP Documentation - CASE TYPE OF