Skip to Content
Author's profile photo Kiran Kumar Valluru

Understanding Widening Cast in ABAP Objects

There are many discussions about Widening cast in SCN. some say, it is Up casting while other say it is Down casting. I remember in a way as depicted below and still following the same.

Let’s take a simple inheritance tree.

          /wp-content/uploads/2013/09/inh_tree_276312.jpg

Narrowing Cast:

/wp-content/uploads/2013/09/2_276311.jpg

Assigning/copying the instance of sub class to super class instance is called Narrowing Cast.

As shown in the figure, assigning sub class to super class is going up wards. From sub class(es) to super class while moving Up the path becomes narrow as shown in the left image. So I simply remember this. Narrowing cast = Up cast 🙂 .

Widening Cast:

/wp-content/uploads/2013/09/3_276313.jpg

Assigning/coping the instance of super class to the sub class instance is called Widening Cast.

This is the reverse of Narrowing cast. As shown in the figure, assigning super class to sub class is going down wards. From super class to sub class while moving Down the path becomes wider as shown in the left image. So I simply remember this – Widening cast = Down cast.

I will still remember the above inheritance tree while referring casting and refer Widening cast as Down casting ( though is is referred as up casting from release 7.0).

Coming to the topic, I use Widening cast in this blog (instead of up/down casting ) .

To understand the Widening cast, I will just explain with the simple program.

Simple Inheritance Report
REPORT zkk_widening_cast_demo.

CLASS lcl_parent DEFINITION.
   PUBLIC SECTION.
     METHODS parent_method.

ENDCLASS.                    “lcl_parent DEFINITION

  CLASS lcl_child DEFINITION INHERITING FROM lcl_parent.
   PUBLIC SECTION.
     METHODS parent_method REDEFINITION.
     METHODS child_method.

ENDCLASS.                    “lcl_child DEFINITION

  CLASS lcl_parent IMPLEMENTATION.

   METHOD parent_method.
     WRITE / ‘Called -> parent method in Parent Class!’.
   ENDMETHOD.                    “parent_method
ENDCLASS.                    “lcl_parent IMPLEMENTATION

CLASS lcl_child IMPLEMENTATION.

   METHOD parent_method.
     WRITE / ‘Called -> parent redifinition method in Child Class!’.
   ENDMETHOD.                    “parent_method
   METHOD child_method.
     WRITE / ‘Called -> child method in Child Class!’.
   ENDMETHOD.                    “child_method

ENDCLASS.                    “lcl_child IMPLEMENTATION

  START-OF-SELECTION.

   DATA: lr_parent TYPE REF TO lcl_parent,
         lr_child  TYPE REF TO lcl_child.

   CREATE OBJECT: lr_parent,lr_child.

   lr_parent->parent_method( ).
   lr_child->parent_method( ).
   lr_child->child_method( ).

Now after executing this I got the below output:

/wp-content/uploads/2013/09/4_276335.jpg

Now I am interested in child(sub) class method in my parent(super) class. Which mean when I call the ‘parent_method’ of parent class in the above report then it should call the ‘parent_method’ of child class( Redefined method call instead of original method call). So I do a Narrowing cast.

continuing the above report.

CREATE OBJECT: lr_parent,lr_child.

   WRITE / 'Before Narrowing Cast:'.
   lr_parent->parent_method( ).
   lr_child->parent_method( ).
   lr_child->child_method( ).

 *  Narrowing cast
   lr_parent = lr_child.

   WRITE / 'After Narrowing Cast:'.
   lr_parent->parent_method( ).
   lr_child->parent_method( ).
   lr_child->child_method( ).

Now when I execute the above report, I get the below output, which is as expected.

/wp-content/uploads/2013/09/5_276337.jpg

Now I am interested in parent(super) class method in my child(sub) class. Which mean when I call the ‘parent_method’ of child class in the above report then it should call the ‘parent_method’ of super class( Super class method call instead of redefined sub class method call). So I do a Widening cast.

CREATE OBJECT: lr_parent,lr_child.

   WRITE / 'Before Widening Cast:'.
   lr_parent->parent_method( ).
   lr_child->parent_method( ).
   lr_child->child_method( ).

   TRY .
 *   Widening Cast
     lr_child ?= lr_parent.
    
     WRITE / 'After Widening Cast:'.
     lr_parent->parent_method( ).
     lr_child->parent_method( ).
     lr_child->child_method( ).
   CATCH cx_sy_move_cast_error.
     WRITE / 'Widening Cast Failed!'.
   ENDTRY.

The output is as below:

/wp-content/uploads/2013/09/6_276338.jpg

After seeing the above output, we remember that ” It is always not possible to do Widening cast as the sub class will have more functionality compared to super class” .

So, I removed the method definition ‘child_method’ in the child class and tried Widening cast. I got the same output!

I created an empty class definitions and tried widening cast to see the widening cast success message 😛 .

CLASS lcl_parent DEFINITION.

ENDCLASS.                    "lcl_parent DEFINITION


CLASS lcl_child DEFINITION INHERITING FROM lcl_parent.

ENDCLASS.                    "lcl_child DEFINITION


CLASS lcl_parent IMPLEMENTATION.

ENDCLASS.                    "lcl_parent IMPLEMENTATION


CLASS lcl_child IMPLEMENTATION.

ENDCLASS.                    "lcl_child IMPLEMENTATION


START-OF-SELECTION.

   DATA: lr_parent TYPE REF TO lcl_parent,
         lr_child  TYPE REF TO lcl_child.

   CREATE OBJECT: lr_parent,lr_child.

   TRY .
*   Widening Cast
     lr_child ?= lr_parent.
     WRITE / 'Widening Cast Success!'.
   CATCH cx_sy_move_cast_error.
     WRITE / 'Widening Cast Failed!'.
   ENDTRY.

Now we will see the output which we are all waiting for!

/wp-content/uploads/2013/09/10_276381.jpg

The Widening cast will always fail unless the assigning instance has the same type of instance to which we are assigning.

So people used to tell do Narrowing cast before Widening Cast!, to have the assigning instance same reference.

I will take the main report and do a narrowing cast before widening cast.

REPORT zkk_widening_cast_demo.

 CLASS lcl_parent DEFINITION.
   PUBLIC SECTION.
     METHODS parent_method.

 ENDCLASS.                    "lcl_parent DEFINITION


 CLASS lcl_child DEFINITION INHERITING FROM lcl_parent.
   PUBLIC SECTION.
     METHODS parent_method REDEFINITION.
     METHODS child_method.

 ENDCLASS.                    "lcl_child DEFINITION


 CLASS lcl_parent IMPLEMENTATION.

   METHOD parent_method.
     WRITE / 'Called -> parent method in Parent Class!'.
   ENDMETHOD.                    "parent_method
 ENDCLASS.                    "lcl_parent IMPLEMENTATION


 CLASS lcl_child IMPLEMENTATION.

   METHOD parent_method.
     WRITE / 'Called -> parent redifinition method in Child Class!'.
   ENDMETHOD.                    "parent_method
   METHOD child_method.
     WRITE / 'Called -> child method in Child Class!'.
   ENDMETHOD.                    "child_method

 ENDCLASS.                    "lcl_child IMPLEMENTATION


 START-OF-SELECTION.

   DATA: lr_parent TYPE REF TO lcl_parent,
         lr_child  TYPE REF TO lcl_child.

   CREATE OBJECT: lr_parent,lr_child.

   WRITE / 'Before Widening Cast:'.
   lr_parent->parent_method( ).
   lr_child->parent_method( ).
   lr_child->child_method( ).

   lr_parent = lr_child. " Narrowing cast

   TRY .
 *   Widening Cast
     lr_child ?= lr_parent.
     WRITE / 'After Widening Cast:'.
     lr_parent->parent_method( ).
     lr_child->parent_method( ).
     lr_child->child_method( ).
   CATCH cx_sy_move_cast_error.
     WRITE / 'Widening Cast Failed!'.
   ENDTRY.

Now lr_parent has same type of lr_child as we did Narrowing cast. We will see the output:

/wp-content/uploads/2013/09/8_276356.jpg

Wow! widening cast is successful this time. But we can see that this output is same as the output of Narrowing cast shown above (which is not what we required).

Because, we have copied the lr_child instance to lr_parent ( lr_parent = lr_child ” Narrow cast) before widening cast. Now lr_parent has same type of lr_child and we assign lr_child ?= lr_parent which is noting but copying child class instance to child class instance!

So, when this Widening cast is actually useful?

To explain this, I will take a simple example using interfaces:

REPORT zkk_widening_cast_demo.

 INTERFACE lif_test.
   METHODS interface_method.
 ENDINTERFACE.                    "lif_test

 CLASS lcl_myclass DEFINITION.
   PUBLIC SECTION.
     INTERFACES lif_test.
 ENDCLASS.                    "lcl_class1 DEFINITION

 CLASS lcl_myclass IMPLEMENTATION.
   METHOD lif_test~interface_method.
     WRITE / 'Interface method call in My Class'.
   ENDMETHOD.                    "lif_test~interface_method
 ENDCLASS.                    "lcl_class1 IMPLEMENTATION


 START-OF-SELECTION.

   DATA: lr_intf TYPE REF TO lif_test,
         lr_mine TYPE REF TO lcl_myclass.

   CREATE OBJECT lr_intf TYPE lcl_myclass.
   TRY .
 *   Widening Cast
       lr_mine ?= lr_intf.
       WRITE /'Widening Cast Successful!'.
     CATCH cx_sy_move_cast_error.
       WRITE / 'Widening Cast Failed!'.
   ENDTRY.
 

Output:

/wp-content/uploads/2013/09/9_276357.jpg

Since we cannot directly assign the interface reference to class reference,

As using, lr_mine = lr_intf   ” will give syntax error because lr_intf is not the same type of lr_mine.

So we do a Widening cast, lr_mine ?= lr_intf , which won’t give syntax check and at run time if lr_intf contains the same reference of lr_mine, the reference will be copied else the exception will be thrown.

Now lets take one more class to understand better.

REPORT zkk_widening_cast_demo.

 INTERFACE lif_test.
   METHODS interface_method.
 ENDINTERFACE.                    "lif_test

 CLASS lcl_myclass DEFINITION.
   PUBLIC SECTION.
     INTERFACES lif_test.
 ENDCLASS.                    "lcl_class1 DEFINITION

 CLASS lcl_yourclass DEFINITION.
   PUBLIC SECTION.
     INTERFACES lif_test.
 ENDCLASS.                    "lcl_class2 DEFINITION

 CLASS lcl_myclass IMPLEMENTATION.
   METHOD lif_test~interface_method.
     WRITE / 'Interface method call in My Class'.
   ENDMETHOD.                    "lif_test~interface_method
 ENDCLASS.                    "lcl_class1 IMPLEMENTATION

 CLASS lcl_yourclass IMPLEMENTATION.

   METHOD lif_test~interface_method.
     WRITE / 'Interface method call in Your class'.
   ENDMETHOD.                    "lif_test~interface_method
 ENDCLASS.                    "lcl_class2 IMPLEMENTATION


 START-OF-SELECTION.

   DATA: lr_intf TYPE REF TO lif_test,
         lr_mine TYPE REF TO lcl_myclass,
         lr_your TYPE REF TO lcl_yourclass.

 *  CREATE OBJECT lr_intf TYPE lcl_myclass.
   CREATE OBJECT lr_intf TYPE lcl_yourclass.

    TRY .
 *      Widening Cast
        lr_mine ?= lr_intf.
        WRITE /'Widening Cast Successful!'.
      CATCH cx_sy_move_cast_error.
        WRITE / 'Widening Cast Failed!'.
    ENDTRY.

In this case the widening cast will be failed since lr_intf is not of same type as lr_mine.

We use widening cast mainly while dealing with interfaces and in case of dynamic programming.

Now, If we look at the below statement

CREATE OBJECT lr_intf TYPE lcl_yourclass.
    TRY .
 *      Widening Cast
        lr_mine ?= lr_intf.
        WRITE /'Widening Cast Successful!'.
      CATCH cx_sy_move_cast_error.
        WRITE / 'Widening Cast Failed!'.
    ENDTRY.

is nothing but Narrowing cast before widening cast,

DATA lr_mine1 TYPE REF TO lcl_myclass.
   CREATE OBJECT lr_mine1.

   lr_intf = lr_mine1.  " Narrowing Cast
   TRY .
 *      Widening Cast
       lr_mine ?= lr_intf.
       WRITE /'Widening Cast Successful!'.
     CATCH cx_sy_move_cast_error.
       WRITE / 'Widening Cast Failed!'.
   ENDTRY.

So in this context, “Do Narrowing cast before Widening cast”  makes sense without confusion!

Hope I tried to explain Widening cast to some extent!.  Comments are welcome 🙂

Assigned Tags

      19 Comments
      You must be Logged on to comment or reply to a post.
      Author's profile photo Former Member
      Former Member

      Hello Kiran,

      I find a few points missing/wrongly stated in the blog -

      The Widening cast will always fail unless the assigning instance has the same type of instance to which we are assigning.

      • This is partially correct. The thumb rule of object reference assignment is - "The dynamic type of the reference should be equal to/more specific than the static type".

           If i rephrase your statement it'll look something like this -

      The Widening cast will always fail unless the the  assigning instance has the same/more specific (dynamic) type of instance to which we are assigning.

      • You have also not mentioned that the casting operator '?=' is just an instruction to the compiler to overlook the types of the LHS & RHS reference variables (during static compilation only). When you use the casting operator the check happens at runtime & if it fails, we get the CX_SY_MOVE_CAST_ERROR.

      BR,

      Suhas

      Author's profile photo Kiran Kumar Valluru
      Kiran Kumar Valluru
      Blog Post Author

      Hi Suhas,

      Thanks for the correction. Yes, It's same/more specific (dynamic) type

      And I think I have mentioned about compiler instruction..

      As using, lr_mine = lr_intf   " will give syntax error because lr_intf is not the same type of lr_mine.

      So we do a Widening cast, lr_mine ?= lr_intf , which won't give syntax check and at run time if lr_intf contains the same reference of lr_mine, the reference will be copied else the exception will be thrown.

      may be not in more detail!. Thanks for mentioning about it 🙂

      Regards,

      Kiran

      Author's profile photo SHANKARANARAYAN KRISHNAMOORTHY
      SHANKARANARAYAN KRISHNAMOORTHY

      Hi Kiran,

      Nice explanation.  It refreshed the concepts in my mind. Would be good if you can give a real world example where narrow and wide casting are used.

      BR,

      Shankar.. 

      Author's profile photo Former Member
      Former Member

      Hi Kiran,

      Very nice explanation.got more clarity.

      regards,

      Vasu

      Author's profile photo Former Member
      Former Member

      Hi

      nice blog 🙂

      Author's profile photo Former Member
      Former Member

      Nice blog! 🙂

      Author's profile photo Former Member
      Former Member

      Well Explained.

      Regards,

      Anoop

      Author's profile photo Yuvaraj Shanmugam
      Yuvaraj Shanmugam

      Hello Kiran,

      Its a great blog and a refreshing read.

      There is one thing that I wanted to say.

      The diagrams that you are using to refer casting is a bit misleading:

      The explanation that you made for the diagram makes sense only if you thing in terms of program lines.

      e.g: Narrowing Cast: lo_parent ?= lo_child..

      The flow of content in this statement is accordance with the diagram. (i.e. It goes from down to up).

      But what happens actually is, The Parent object sits in the shoes of The Child object.

      i.e. The specificity of the object is increased. The object refernce is now more specific (Audi) from being generic(Car). That is why it's called a Narrowing cast.

      When the object is Wide casted, its meaning becomes more generic (more wide).

      Just my 2 cents...

      Author's profile photo Former Member
      Former Member

      hi kiran ....

      gud info

      Author's profile photo Chirag I. Keswani
      Chirag I. Keswani

      This was the best example one could find for narrow and wide casting. Just amazing. You have explained it in detail with all the screen shots. Great job man. 🙂

      Author's profile photo Roman Beketov
      Roman Beketov

      Hi! No, you are not correct and article not correct lo_child ?= lo_parent - it is Down Cast(Narrowing Cast) (see course BC401. page 150),

      and Yuvaraj S wrote right.

      Author's profile photo Former Member
      Former Member

      Well explained.. Very nice document. Thanks for sharing!

      regards,

      Sachin

      Author's profile photo Joao Sousa
      Joao Sousa

      I think this blog is a bit too long, and not to the point.

      For one, I don't like term widening cast as it is a bit misleading, since you are not actually widening something, you are regaining access to what is already there. You are widening the reference type, not the object itself.

      Assigning/copying the instance of sub class to super class instance is called Narrowing Cast.

      This phrase is again a bit misleading because you are not copying "from a subclass to a super class". You are assigning an instance to a different reference type, the object doesn't change.

      The conclusion is simple: The reference must of the exact same type, or a parent, of the object's type.

      EDIT: As I think this is very important, I wrote Object Casting - Reference type vs Object Type

      Author's profile photo Former Member
      Former Member

      Hi ,

          i am bit confused ,because in your post you explained like Narrowing cast = Up cast and

        Widening cast = Down cast. But,in sap keyword Documentation .this description is given like

      Up Cast

      If the static type of the target variable is less specific or the same as the static type of the source variable, assignment is always possible. The name up cast arises from the fact that you are moving upwards within the inheritance space. As the target variable can accept more dynamic types in comparison to the source variable, this assignment is also know as a widening cast. An up cast is possible in all ABAP statements in which the content of a data object is assigned to another data object. This includes, for example, assignments with the normal assignment operator (=), the insertion of rows in internal tables, or passes from actual to formal parameters.

      Down Cast

      If the static type of the target variable is more specific than the static type of the source variable, you must check at runtime before the assignment is executed, whether it is less specific or the same as the dynamic type of the source variable. The name down cast arises from the fact that you are moving downwards in the inheritance space. Because the target variable can accept fewer dynamic types in comparison to the source variable, this assignment is also known as a narrowing cast. A down cast is only possible using the special assignment operator ?= (casting operator) or the statement MOVE ... ?TO .... If this prerequisite is not met, a handleable exception is raised.

      FYI.

      http://help.sap.com/abapdocu_702/en/abenconversion_references.htm

      please clarify.

      Regards,

      Krishna,

      Author's profile photo Kiran Kumar Valluru
      Kiran Kumar Valluru
      Blog Post Author

      Hi,

      Yes, It's Up casting. It was already mentioned in the blog. Please check again!

      I will still remember the above inheritance tree while referring casting and refer Widening cast as Down casting ( though is is referred as up casting from release 7.0).

      Coming to the topic, I use Widening cast in this blog (instead of up/down casting ) .

                ( You may also check the first line of the blog if you haven't read it)

      For understanding purpose(or to remember) I used the old terms. The names/terms (Up/down) was vice-versed/interchanged from release version 7 or higher!

      The SAP Help links for release 6.40 is not available. If you see in the F1 help for ?= operator in 6.40 version you can see the old term. You may check this discussion for reference: Change Narrowing and Widening Cast

      I hope you understood the concept of casting and for the Naming/terms I advise to follow according to your course material or the latest help doc.

      Regards,

      Kiran

      Author's profile photo Former Member
      Former Member

      Hello Kiran,

      Nice document, Well explained, newbies like me can easily understand! got more clarity.

      Thanks,

      KK

      Author's profile photo Scott Silburn
      Scott Silburn

      Note that SAP in BC401 says that NARROWcasting is the same as DOWNcasting and that this involves the assignment of a SUPERclass to a SUBclass, e.g. lr_truck ?= lr_vehicle.

      Author's profile photo Paneendra Kumar PG
      Paneendra Kumar PG

      acording to the SAP  taw12 part one   down-cast = narrowing-cast and up-cast = widening cast.... 😛

      Author's profile photo Former Member
      Former Member

      Looked many discussions. This is very informative, Nice Blog, Thanks for sharing. 🙂

      Cheers,

      Alfred