Skip to Content

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

disappointed?  🙂

The above example was taken from one of the tweets of  Uwe Fetzer and is the motivation for writing this blog.

/wp-content/uploads/2013/09/7_276340.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 🙂

To report this post you need to login first.

19 Comments

You must be Logged on to comment or reply to a post.

  1. Suhas Saha

    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

    (0) 
    1. Kiran Kumar Valluru 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

      (0) 
  2. 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…

    (0) 
  3. 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. 🙂

    (0) 
  4. 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.

    (0) 
  5. 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

    (0) 
  6. krishna **

    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,

    (0) 
    1. Kiran Kumar Valluru 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

      (0) 
  7. 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.

    (0) 

Leave a Reply