MichaelB.
7/28/2018 - 10:58 AM

Use narrowing cast

A superclass reference variable can point to a subclass object at runtime using Narrowing Cast. That makes a reference variable not only a pointer to an object of a class, but also a pointer to one of its subclasses. Narrowing cast makes our object reference variable see a narrower scope of object elements. We can assign a subclass object to a variable that holds a reference to superclass object at runtime. The subclass contains all the methods and all the attributes of the superclass so inheritance allows this to happen. This data object variable can only access the elements available in the subclass through inheritance. Only the methods and attributes that exist in the superclass can be referenced/called directly. You can use the TYPE addition of CREATE OBJECT to directly specify the class to create the object from.

The superclass reference variable only knows about the elements defined within the superclass, so it can only directly access these elements. It cannot reference any of the additional elements part of the subclass. This is called narrowing cast. The superclass reference variable has a narrower, less specific view of the object it points to. Our reference variables can point to different objects at runtime. Doing so makes our reference variables, dynamic type reference variables instead of static type reference variables. Narrow casting causes superclass to only be able to perform methods on the subclass object that were first defined in the superclass and only access attributes that were part of the superclass to begin and have been inherited by the subclass -> superclass reference variable has a narrower scope.

* Example of an explicit narrowing cast, causes superclass reference variable to point to subclass

DATA:   car      TYPE REF TO superclass,
        mercedes TYPE REF TO subclass.
CREATE OBJECT car.
CREATE OBJECT mercedes.
car = mercedes.

******************************************
* How to use the TYPE addition of CREATE OBJECT to directly specify the class to create the object from (implicit narrowing cast).

DATA:   car      TYPE REF TO superclass,
        mercedes TYPE REF TO subclass.

CREATE OBJECT car TYPE mercedes.
        
***************************************
* Narrowing cast example


START-OF-SELECTION.

  DATA vehicle1 TYPE REF TO vehicle.
  DATA car1     TYPE REF TO car.

* Vehicle object without any NARROWING CAST
  WRITE: / 'Vehicle object without any NARROWING CAST'.
  CREATE OBJECT vehicle1.
  vehicle1->gofaster( ).
  CLEAR vehicle1.

* Vehicle object with NARROWING CAST
  WRITE: / 'Vehicle - NARROWING CAST from Car'.
  CREATE OBJECT car1.
  vehicle1 = car1.
  vehicle1->gofaster( ).

* Demonstrate WIDENING CAST
* At this point we have used a NARROWING cast on VEHICLE1
* Create an obj ref to catch the error. You don't need to do this. You can just
* use CATCH SYSTEM-EXCEPTIONS move_cast_error = 4.

DATA: my_cast_error TYPE REF TO cx_sy_move_cast_error,
      car2          TYPE REF TO car.
* Note, we haven't created an object for car2... it is an empty ref variable

TRY.
* Do a WIDENING CAST to move the ref from VEHICLE TO CAR (more specific)
  car2 ?= vehicle1.
  CATCH cx_sy_move_cast_error INTO my_cast_error.
    WRITE: / 'The WIDENING CAST failed'.
ENDTRY.
IF car2 is not INITIAL.
  car2->gofaster( ).
  car2->writespeed( ).
ENDIF.

* Now, lets generate an error

  CLEAR: car1, car2, vehicle1, my_cast_error.
  CREATE OBJECT vehicle1.
  TRY.
  car1 ?= vehicle1.
  CATCH cx_sy_move_cast_error INTO my_cast_error.
    WRITE: / 'The WIDENING CAST failed'.
ENDTRY.
IF car2 is not INITIAL.
  car2->gofaster( ).
  car2->writespeed( ).
ENDIF.