Skip to Content
Author's profile photo Joao Sousa

Object Casting – Reference type vs Object Type

I’m writing this blog after reading Understanding Widening Cast in ABAP Objects since it became clear to me that the difference between reference types and object type is not clear for many SCN users who are not used to Object Oriented Programming. Knowing the difference between the two is critical to understanding what you can do with casting and how powerful the concept of inheritance is.

I’ll start by giving an example of why narrowing cast is so important. Imagine the following scenario, where the specific fruits are children of the super class Fruit:

/wp-content/uploads/2014/07/inheritance_501537.png

You want to create a table of fruit, then loop at it, and write the name of the fruit to the screen. The required data should can be declared as:


DATA: lt_fruits TYPE TABLE OF REF TO ZCL_FRUIT,
            lo_fruit  TYPE  REF TO ZCL_FRUIT,
            lo_mango TYPE REF TO ZCL_MANGO,
            lo_apple  TYPE REF TO ZCL_APPLE,
            lo_orange TYPE REF TO ZCL_ORANGE.



And then you do something like:


lo_mango = new ZCL_MANGO( ).
lo_fruit ?= lo_mango.
append lo_fruit to lt_fruit.



This is where the difference between reference type and object type becomes critical.

  • The object type is intrinsic to the class of the constructor (new ZCL_MANGO) used to bring it to “life”. Think of the object as memory space that contains information, whose type never changes after it is instantiated.
  • The reference type is the type of the pointer (in this case lo_mango and lo_fruit) to the memory space. It’s your gateway, your “API”,  only through them can you access the memory (the intrinsic object, whose type was determined by the constructor).

When I make a cast from lo_mango to lo_fruit, the object itself and therefore its type remains the same. Same variables, same type,  nothing changes except the type of the pointer, the reference. As long as we use a reference of the super class type we only have access in the code to the attributes and methods of the superclass, but that doesn’t mean the attributes of the original object were lost. They are still there waiting!

This dichotomy is very important, because it allows us to keep similar objects together, in the same table for example, while keeping their intrinsic properties intact. For example lets assume that for the very specific case of the Apple we want to output the apple’s type besides the name of the fruit, the code would be something like:


Loop at lt_fruit into lo_fruit.
     write lo_fruit->get_name( ).
     if cl_abap_classdescr=>get_class_name( lo_fruit ) = 'ZCL_APPLE'.
          lo_apple ?= lo_fruit.
          write lo_apple->get_type_of_apple( ).
     endif.
Endloop.





It should be become even clearer by the usage of cl_abap_classdescr=>get_class_name( lo_fruit ) and the fact that it returns ZCL_APPLE (instead of ZCL_FRUIT), that indeed the object retains all the attributes that were given to him by the constructor, even if the reference is of the super class type.

Now imagine a scenario where casting didn’t exist, and the code you would need. You would need 3 tables, 3 loops. Now expand this to a real program, inheritance allow much more elegant coding.

Assigned Tags

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

      nice one!

      i am was looking for a blog on static and dynamic types.also tried sap documentation but got nothing.everything is still blurred.

      what is dont get is. in narrow casting is.

      see code and comments.

      sorry for posting this entire code ,makes your blog messy.

      class vehicle definition.

        public section.

          methods: m1 ,

          m2.

      endclass.                    "vehicle DEFINITION

      class vehicle implementation.

        method m1.

          write /'method m1 super class imple.'.

        endmethod.                    "m1

        method m2.

          write /'method m2 super class imple.'.

        endmethod.                    "m1

      endclass.                    "vehicle IMPLEMENTATION

      class truck definition inheriting from vehicle.

        public section.

          methods:

          m2 redefinition,

          m4.

      endclass.                    "truck DEFINITION

      class truck implementation.

        method m2 .

          write /'method m2 redefination sub class imple.'.

        endmethod.                    "m2

        method m4.

      *      method m1.

          write /'method m4 sub class imple.'.

      *  endmethod.

        endmethod.                    "m4

      endclass.                    "truck IMPLEMENTATION

      start-of-selection .

        data : o_super type ref to vehicle,

              o_sub type ref to truck.

        create object :o_super , o_sub .

        o_super = o_sub."up/narrow casting "assigning child to parent

        call method o_super->m2. "redefined method will be called.

      " below statement throw a syntax error"not possible to access those

      *method which are not defined in super class

      *call method o_super->m4.

      call method o_super->('m4'). "works fine WHY!!!!!!

      *need not to say prog is getting dump but still no syntax error.

      Author's profile photo Joao Sousa
      Joao Sousa
      Blog Post Author

      Like I say in the blog the Reference type of o_super is Vehicle so you can only call methods of Vehicle through it. The reference is the API, and Vehicle doesn't have the method (the object does, but not the reference) so you get syntax error.

      On the other hand when you call o_super->('m4') you are accessing a method that exists in the Vehicle class, the ->( ) operator. Since the object itself does have the method m4, the call works.

      The reference type is all about the syntax, what attributes and methods are available to the programmer. The ->( ) is available but shouldn't be used unless in very specific situations because it obfuscates your code, and can easily lead to runtime errors.

      Author's profile photo Former Member
      Former Member

      " below statement throw a syntax error"not possible to access those

      *method which are not defined in super class

      *call method o_super->m4.

      call method o_super->('m4'). "works fine WHY!!!!!!

      It is very easy to explain this if you think along the line of static & dynamic types. When the compiler compiles the code (read: statically), it finds that M4( ) is not defined for the static type (o_super). Thus, it raises a syntax error.

      When you use dynamic token to call the method o_super->('M4'), the compiler doesn't check the existence of the method and leaves it to the ABAP Runtime Environment(RTE) to handle it. Therefore you do not get a syntax error, but may/may not get an RT error depending on your case.

      i am was looking for a blog on static and dynamic types.also tried sap documentation but got nothing.everything is still blurred.

      In layman's terms -

      • Static type - The type of the reference variable when it is declared in the code using DATA <ref_var> TYPE REF TO <whatever>.
      • Dynamic type - The type of the instance/object which the reference variable points to during runtime of the code.

      Where is the difficulty in understanding this?

      - Suhas

      Author's profile photo Former Member
      Former Member

      OK I am getting this.may be

      Suppose I have created a static type variable

      Data oref type ref to  zcl_fruit.

      The above one variable is of static type or object type(joao terms).

      How can I convert it into dynamic type....or if I am understanding this right

      After casting whether narrow or wide casting... It becomes of dynamic type.

      As soon as we assign another instance or another static  variable to this.it becomes of dynamic type.

      Please correct me if I  still misunderstood the concept.

      Author's profile photo Joao Sousa
      Joao Sousa
      Blog Post Author

      How can I convert it into dynamic type....or if I am understanding this right

      You don't convert it, they are separated things (static and dynamic). That's the problem with using "dynamic type" to label something that never changes, the object type (instance in memory).

      I didn't use the term "static type" I used "reference type" and "object type", because the type is attached to a real thing:

      • Oref is a reference (you even called it a ref).
      • the output of new ZCL_APPLE is an object
      • You make the reference (ORefApple) point to the object (new ZCL_APPLE). The reference is like an address that tells you where the object is in the memory space.

      OrefApple = new ZCl_APPLE( ).

      The left side is the reference, the right side is the object. We assign the object to a reference during the instanciation so we can access it, but the object type will never change, it will always be ZCL_APPLE.

      When we do:

      Oref ?= OrefApple

      We are only changing the type of the reference (the static type according to SAP). Not the object, because the type of the object never changes (the so called dynamic type, that never changes .... worse name ever).

      Author's profile photo Former Member
      Former Member

      Hello Joao,

      This is where the difference between reference type and object type becomes critical.

      I am sure by "reference" & "object" types you mean "dynamic" & "static" type respectively. The whole point of "casting" becomes clear if the developer understands this very important rule -

      The dynamic type is always more specific than or the same as the static type.

      I don't think of this in the complex way like pointer to the memory et al. I know what my static & dynamic types are and then decide whether i'll be needing the casting operator (?=).

      I not sure if the same applies to other programming languages viz., Java, C# etc. But the concept of "static" & "dynamic" types works just fine for ABAP 😎

      You can even extend this logic to data reference variables.

      BR,

      Suhas

      PS -Tbh I always forget which is "narrowing" & which is "widening" cast.

      Author's profile photo Joao Sousa
      Joao Sousa
      Blog Post Author

      I am sure by "reference" & "object" types you mean "dynamic" & "static" type respectively.

      The problem is that those (SAP specifc) terms are even more abstract. Dynamic and static in relation to what? I think it is much easier to understand if we use less abstract terms.

      I don't think of it in the complex way like pointer to the memory et al. I know what my static & dynamic types are and then decide whether i'll be needing the casting operator (?=).

      The "complex way" as you call it, is understanding what is happening in the background instead of memorizing what 2 terms mean. It's how you learn it in C++, and how you are able to shift easily from ABAP to Java (for example) that uses completely different terminology (always understand the concept instead of memorizing the semantics).

      I not sure if the same applies to other programming languages viz., Java, C# etc. But the concept of "static" & "dynamic" types works just fine for ABAP 😎

      The terms "static" and "dynamic" type aren't used outside SAP in this context, as far as I know.

      Author's profile photo Former Member
      Former Member

      The "complex way" as you call it, is understanding what is happening in the background instead of memorizing what 2 terms mean. It's how you learn it in C++ ...

      I am a Mechanical engineer who ended up being a ABAP programmer. So i did not have any C# or Java programming during my engineering.

      The problem is that those (SAP specific) terms are even more abstract.

      Actually these are the "terms" which are used by Horst Keller in his book on ABAP Objects. And IMO these terms are just synonyms of what you call the "reference" and "object" types. The underlying concept is the same, it is just his way of explaining the concept.

      Dynamic and static in relation to what?

      There is no relation between the two. Because they are totally different.

      Reference variables have no type. The are pointers which "point" to the relevant object/data references during runtime. The "ABAP" concept (if you may call it so),says & i quote (ABAP Keyword Documentation) -

      • The dynamic type is defined at runtime of the program, and is the data type of the data object or the class of the object to which the reference variable "points".
      • The static type is set with the declaration of the reference variable.

      The static type doesn't point to anything, it is just an indicator which does the following -

      • Tells the compiler to do the static compilation checks e.g, method/attribute names
      • Tells the RTE to do the runtime checks e.g., dynamic methods, casting

      I don't quite see how the "ABAP" concept is different from the concept you have explained, except for the terminology.

      Author's profile photo Joao Sousa
      Joao Sousa
      Blog Post Author

      Actually these are the "terms" which are used by Horst Keller in his book on ABAP Objects. And IMO these terms are just synonyms of what you call the "reference" and "object" types. The underlying concept is the same, it is just his way of explaining the concept.

      The problem is that:

      • The terms are misleading, since they call dynamic type to something that never changes. They may be synonyms, but they are poor descriptions of the concepts.
      • They are very specific to ABAP. Even if you want to program ABAP for the rest of your life that's fine, but even in the SAP world you interact with other languages like Javascript.

      The static type doesn't point to anything, it is just an indicator which does the following

      Of course not, and I never said it did. The reference does.

      I am a Mechanical engineer who ended up being a ABAP programmer. So i did not have any C# or Java programming knowledge.

      Regardless, what I said stands. Learning the "why" is much better then memorizing terms, that are very specific one programming language.

      Author's profile photo Former Member
      Former Member

      Even you want to program ABAP for the rest of your life that's fine, but even in the SAP world you interact with other languages like Javascript.

      Maybe you did not understand my point. What i am trying to say is that the concept of casting (or assigning reference variables) is the same, just the terms are different.

      It is ambiguous/misleading to you because you have learnt it in a different way (object/reference types). But for me it is not because i learnt it the ABAP (or Horst Keller's) way 😛

      Let me confess that i had difficulties to understand the concept initially. But after debugging the RTTS & SALV classes, reading the OO gurus' content on SCN; i finally figured out what those terms really meant.

      I think each of us entitled to his/her way of understanding, so let the community decide which one to choose.

      Learning the "why" is much better then memorizing terms, that are very specific one programming language.

      Can you please tell me how the "why" is different? Maybe i am too short sighted to see it.

      BR,

      Suhas

      Author's profile photo Joao Sousa
      Joao Sousa
      Blog Post Author

      It is ambiguous/misleading to you because you have learnt it in a different way (object/reference types). But for me it is not because i learnt it the ABAP (or Horst Keller's) way 😛

      Nothing is misleading after you know exactly what it is. You said it yourself, that you had difficulty understanding the concepts, and you had to debug. That shows the terms are confusing.

      I think each of us entitled to his/her way of understanding, so let the community decide which one to choose.

      Yes I agree, yet you started this discussion by saying "I am sure by "reference" & "object" types you mean "dynamic" & "static" type respectively.", like I was saying something wrong.

      Author's profile photo Former Member
      Former Member

      That shows the terms are confusing.

      No, that shows that i did not have any prior OO knowledge & that my brain has slow processing power.

      like I was saying something wrong.

      No. I wanted to ask if i understood the terms correctly, because they were new to me. That's why i even asked if the "static", "dynamic" terms were ABAP-specific.


      It was never my intention to correct you. I was just supplementing what you had mentioned.

      Author's profile photo Former Member
      Former Member

      Hi Joao,

      nice and useful blog for many, I am sure. I have just few comments:

      1. In your first example, it should rather be:

        lo_mango = new_zcl_mango( ). 
        lo_fruit = lo_mango.
        append lo_fruit to lt_fruit. 

        Since it's an UpCast, then use "=" instead of "?=" even though using "?=" is technically and syntactically possible. However, it's confusing the reader here.

      2. To be precise, it should say
        The object type is intrinsic to the class of which the constructor (new ZCL_MANGO) used to bring it to "life".
        instead of
        The object type is intrinsic to the type of the constructor (new ZCL_MANGO) used to bring it to "life".
        as the constructor has no type... And it's also a factory method here, not a constructor (but this is another story) and this we all understand.
      3. For better understanding of terms static
        and dynamic, I recommend the readers to simply check the following program in the debugger (definitions and implementations of superclass lcl_fruit and its subclasses lcl_apple and lcl_mango are omitted here to keep it short):

        DATA:
           lt_fruit TYPE TABLE OF REF TO lcl_fruit,
           lo_fruit TYPE REF TO lcl_fruit,
           lo_apple TYPE REF TO lcl_apple,
           lo_mango TYPE REF TO lcl_mango.

        START-OF-SELECTION.
           CREATE OBJECT lo_apple.
           lo_fruit = lo_apple.
           APPEND lo_fruit TO lt_fruit.
           CREATE OBJECT lo_mango.
           lo_fruit = lo_mango.
           APPEND lo_fruit TO lt_fruit.
           LOOP AT lt_fruit INTO lo_fruit. "<-- check lo_fruit in debugger in detail
             TRY.
                 lo_apple ?= lo_fruit.
                 lo_apple->write_fruit_name( ).
               CATCH cx_sy_move_cast_error.
                 lo_mango ?= lo_fruit.
                 lo_mango->write_fruit_name( ).
             ENDTRY.
           ENDLOOP.

        Static type of lo_fruit is ref to lcl_fruit, but its dynamic type (which is determined in runtime) is either ref to lcl_apple or ref to lcl_mango depending on which record is actually being processed. In the debugger, the dynamic type is displayed as:
        {O:3*\PROGRAM=ZCAST\CLASS=LCL_APPLE}
        or
        {O:4*\PROGRAM=ZCAST\CLASS=LCL_MANGO}

      4. Actually, several times repeated sentence
        The dynamic type is always more specific than or the same as the static type.
        is the key here. That one also explains why the Uwe Fetzer's example in the referred blog http://scn.sap.com/community/abap/blog/2013/09/09/understanding-widening-cast-in-abap-objects did not work.
      5. I like your explanation of understanding the reference to data or object as an API to the actual data or object in the memory. And yes - I also always prefer understanding WHY the things work the way they do 🙂 !

      BR, Michal

      Author's profile photo Joao Sousa
      Joao Sousa
      Blog Post Author

      Hello,

      I left 1 as it is, since I think it brings forward the fact that the two reference types aren't the same. Corrected nº2.

      Thanks

      Author's profile photo Former Member
      Former Member

      Hi Joao,

      as the blog is on inheritance topic where the subclass-superclass relation is the core and the direction of the assignment is the main thing, then I don't agree, sorry. I think that using the assignment operators as strictly as they should be would help very much the readers for better understanding of the difference:

      lo_superclass = lo_subclass.   "UpCast

      lo_subclass ?= lo_superclass.   "DownCast

      This is commonly used convention. Using the ?= operator in both cases makes the difference less visible. If the developer is not sure why exactly is he/she using each of those different operators in specific case, then it could lead to less readable code and future errors.

      BR, Michal

      Author's profile photo Scott Silburn
      Scott Silburn

      Note that SAP says in BC401 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.